Home | History | Annotate | Download | only in private
      1 /*
      2  *
      3  * Copyright 2015 gRPC authors.
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  *
     17  */
     18 
     19 #import "NSDictionary+GRPC.h"
     20 
     21 #include <grpc/support/alloc.h>
     22 
     23 #pragma mark Category for binary metadata elements
     24 
     25 @interface NSData (GRPCMetadata)
     26 + (instancetype)grpc_dataFromMetadataValue:(grpc_metadata *)metadata;
     27 
     28 // Fill a metadata object with the binary value in this NSData.
     29 - (void)grpc_initMetadata:(grpc_metadata *)metadata;
     30 @end
     31 
     32 @implementation NSData (GRPCMetadata)
     33 + (instancetype)grpc_dataFromMetadataValue:(grpc_metadata *)metadata {
     34   // TODO(jcanizales): Should we use a non-copy constructor?
     35   return [self dataWithBytes:GRPC_SLICE_START_PTR(metadata->value)
     36                       length:GRPC_SLICE_LENGTH(metadata->value)];
     37 }
     38 
     39 - (void)grpc_initMetadata:(grpc_metadata *)metadata {
     40   metadata->value = grpc_slice_from_copied_buffer(self.bytes, self.length);
     41 }
     42 @end
     43 
     44 #pragma mark Category for textual metadata elements
     45 
     46 @interface NSString (GRPCMetadata)
     47 + (instancetype)grpc_stringFromMetadataValue:(grpc_metadata *)metadata;
     48 
     49 // Fill a metadata object with the textual value in this NSString.
     50 - (void)grpc_initMetadata:(grpc_metadata *)metadata;
     51 @end
     52 
     53 @implementation NSString (GRPCMetadata)
     54 + (instancetype)grpc_stringFromMetadataValue:(grpc_metadata *)metadata {
     55   return [[self alloc] initWithBytes:GRPC_SLICE_START_PTR(metadata->value)
     56                               length:GRPC_SLICE_LENGTH(metadata->value)
     57                             encoding:NSUTF8StringEncoding];
     58 }
     59 
     60 // Precondition: This object contains only ASCII characters.
     61 - (void)grpc_initMetadata:(grpc_metadata *)metadata {
     62   metadata->value = grpc_slice_from_copied_string(self.UTF8String);
     63 }
     64 @end
     65 
     66 #pragma mark Category for metadata arrays
     67 
     68 @implementation NSDictionary (GRPC)
     69 + (instancetype)grpc_dictionaryFromMetadataArray:(grpc_metadata_array)array {
     70   return [self grpc_dictionaryFromMetadata:array.metadata count:array.count];
     71 }
     72 
     73 + (instancetype)grpc_dictionaryFromMetadata:(grpc_metadata *)entries count:(size_t)count {
     74   NSMutableDictionary *metadata = [NSMutableDictionary dictionaryWithCapacity:count];
     75   for (grpc_metadata *entry = entries; entry < entries + count; entry++) {
     76     char *key = grpc_slice_to_c_string(entry->key);
     77     NSString *name = [NSString stringWithCString:key encoding:NSASCIIStringEncoding];
     78     gpr_free(key);
     79     if (!name || metadata[name]) {
     80       // Log if name is nil?
     81       continue;
     82     }
     83     id value;
     84     if ([name hasSuffix:@"-bin"]) {
     85       value = [NSData grpc_dataFromMetadataValue:entry];
     86     } else {
     87       value = [NSString grpc_stringFromMetadataValue:entry];
     88     }
     89     metadata[name] = value;
     90   }
     91   return metadata;
     92 }
     93 
     94 // Preconditions: All keys are ASCII strings. Keys ending in -bin have NSData values; the others
     95 // have NSString values.
     96 - (grpc_metadata *)grpc_metadataArray {
     97   grpc_metadata *metadata = gpr_malloc([self count] * sizeof(grpc_metadata));
     98   grpc_metadata *current = metadata;
     99   for (NSString *key in self) {
    100     id value = self[key];
    101     current->key = grpc_slice_from_copied_string(key.UTF8String);
    102     if ([value respondsToSelector:@selector(grpc_initMetadata:)]) {
    103       [value grpc_initMetadata:current];
    104     } else {
    105       [NSException raise:NSInvalidArgumentException
    106                   format:@"Metadata values must be NSString or NSData."];
    107     }
    108     ++current;
    109   }
    110   return metadata;
    111 }
    112 @end
    113