|  | @@ -19,11 +19,15 @@
 | 
	
		
			
				|  |  |  #ifndef GRPCPP_IMPL_CODEGEN_METADATA_MAP_H
 | 
	
		
			
				|  |  |  #define GRPCPP_IMPL_CODEGEN_METADATA_MAP_H
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +#include <grpc/impl/codegen/log.h>
 | 
	
		
			
				|  |  |  #include <grpcpp/impl/codegen/slice.h>
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  namespace grpc {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  namespace internal {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +const char kBinaryErrorDetailsKey[] = "grpc-status-details-bin";
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  class MetadataMap {
 | 
	
		
			
				|  |  |   public:
 | 
	
		
			
				|  |  |    MetadataMap() { memset(&arr_, 0, sizeof(arr_)); }
 | 
	
	
		
			
				|  | @@ -32,24 +36,54 @@ class MetadataMap {
 | 
	
		
			
				|  |  |      g_core_codegen_interface->grpc_metadata_array_destroy(&arr_);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  void FillMap() {
 | 
	
		
			
				|  |  | -    for (size_t i = 0; i < arr_.count; i++) {
 | 
	
		
			
				|  |  | -      // TODO(yangg) handle duplicates?
 | 
	
		
			
				|  |  | -      map_.insert(std::pair<grpc::string_ref, grpc::string_ref>(
 | 
	
		
			
				|  |  | -          StringRefFromSlice(&arr_.metadata[i].key),
 | 
	
		
			
				|  |  | -          StringRefFromSlice(&arr_.metadata[i].value)));
 | 
	
		
			
				|  |  | +  grpc::string GetBinaryErrorDetails() {
 | 
	
		
			
				|  |  | +    // if filled_, extract from the multimap for O(log(n))
 | 
	
		
			
				|  |  | +    if (filled_) {
 | 
	
		
			
				|  |  | +      auto iter = map_.find(kBinaryErrorDetailsKey);
 | 
	
		
			
				|  |  | +      if (iter != map_.end()) {
 | 
	
		
			
				|  |  | +        return grpc::string(iter->second.begin(), iter->second.length());
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    // if not yet filled, take the O(n) lookup to avoid allocating the
 | 
	
		
			
				|  |  | +    // multimap until it is requested.
 | 
	
		
			
				|  |  | +    // TODO(ncteisen): plumb this through core as a first class object, just
 | 
	
		
			
				|  |  | +    // like code and message.
 | 
	
		
			
				|  |  | +    else {
 | 
	
		
			
				|  |  | +      for (size_t i = 0; i < arr_.count; i++) {
 | 
	
		
			
				|  |  | +        if (strncmp(reinterpret_cast<const char*>(
 | 
	
		
			
				|  |  | +                        GRPC_SLICE_START_PTR(arr_.metadata[i].key)),
 | 
	
		
			
				|  |  | +                    kBinaryErrorDetailsKey,
 | 
	
		
			
				|  |  | +                    GRPC_SLICE_LENGTH(arr_.metadata[i].key)) == 0) {
 | 
	
		
			
				|  |  | +          return grpc::string(reinterpret_cast<const char*>(
 | 
	
		
			
				|  |  | +                                  GRPC_SLICE_START_PTR(arr_.metadata[i].value)),
 | 
	
		
			
				|  |  | +                              GRPC_SLICE_LENGTH(arr_.metadata[i].value));
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +    return grpc::string();
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  std::multimap<grpc::string_ref, grpc::string_ref>* map() { return &map_; }
 | 
	
		
			
				|  |  | -  const std::multimap<grpc::string_ref, grpc::string_ref>* map() const {
 | 
	
		
			
				|  |  | +  std::multimap<grpc::string_ref, grpc::string_ref>* map() {
 | 
	
		
			
				|  |  | +    FillMap();
 | 
	
		
			
				|  |  |      return &map_;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    grpc_metadata_array* arr() { return &arr_; }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |   private:
 | 
	
		
			
				|  |  | +  bool filled_ = false;
 | 
	
		
			
				|  |  |    grpc_metadata_array arr_;
 | 
	
		
			
				|  |  |    std::multimap<grpc::string_ref, grpc::string_ref> map_;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  void FillMap() {
 | 
	
		
			
				|  |  | +    if (filled_) return;
 | 
	
		
			
				|  |  | +    filled_ = true;
 | 
	
		
			
				|  |  | +    for (size_t i = 0; i < arr_.count; i++) {
 | 
	
		
			
				|  |  | +      // TODO(yangg) handle duplicates?
 | 
	
		
			
				|  |  | +      map_.insert(std::pair<grpc::string_ref, grpc::string_ref>(
 | 
	
		
			
				|  |  | +          StringRefFromSlice(&arr_.metadata[i].key),
 | 
	
		
			
				|  |  | +          StringRefFromSlice(&arr_.metadata[i].value)));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  }  // namespace internal
 | 
	
		
			
				|  |  |  
 |