1# MPMessagePack
2
3[MessagePack](http://msgpack.org/) framework.
4
5MessagePack is an efficient binary serialization format. It lets you exchange data among multiple languages like JSON. But it's faster and smaller.
6
7# Podfile
8
9```ruby
10pod "MPMessagePack"
11```
12
13# Cartfile
14
15```
16github "gabriel/MPMessagePack"
17```
18
19# MPMessagePack
20
21## Writing
22
23```objc
24#import <MPMessagePack/MPMessagePack.h>
25
26NSDictionary *dict =
27  @{
28    @"n": @(32134123),
29    @"bool": @(YES),
30    @"array": @[@(1.1f), @(2.1)],
31    @"body": [NSData data],
32  };
33
34NSData *data = [dict mp_messagePack];
35```
36
37Or via ```MPMessagePackWriter```.
38
39```objc
40NSError *error = nil;
41NSData *data = [MPMessagePackWriter writeObject:dict error:&error];
42```
43
44If you need to use an ordered dictionary.
45
46```objc
47MPOrderedDictionary *dict = [[MPOrderedDictionary alloc] init];
48[dict addEntriesFromDictionary:@{@"c": @(1), @"b": @(2), @"a": @(3)}];
49[dict sortKeysUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
50NSData *data = [dict mp_messagePack];
51```
52
53## Reading
54
55```objc
56id obj = [MPMessagePackReader readData:data error:&error];
57```
58
59```objc
60MPMessagePackReader *reader = [[MPMessagePackReader alloc] initWithData:data];
61id obj1 = [reader read:&error]; // Read an object
62id obj2 = [reader read:&error]; // Read another object
63```
64
65# RPC
66
67See [msgpack-rpc](https://github.com/msgpack-rpc/msgpack-rpc).
68
69It also supports a framing option where it will prefix the rpc message with the number of bytes (as a msgpack'ed number).
70
71## Client
72
73Request with completion block:
74
75```objc
76MPMessagePackClient *client = [[MPMessagePackClient alloc] init];
77[client openWithHost:@"localhost" port:93434 completion:^(NSError *error) {
78  // If error we failed
79  [client sendRequestWithMethod:@"test" params:@[@{@"arg": @(1)}] completion:^(NSError *error, id result) {
80    // If error we failed
81    // Otherwise the result
82  }];
83}];
84```
85
86You can also request synchronously:
87
88```objc
89NSError *error = nil;
90id result = [client sendRequestWithMethod:@"test" params:@[@{@"arg": @(1)}] messageId:3 timeout:5.0 error:&error];
91// error.code == MPRPCErrorRequestTimeout on timeout
92```
93
94And cancel in progress requests:
95
96```objc
97BOOL cancelled = [client cancelRequestWithMessageId:3];
98// cancelled == YES, if the request was in progress and we cancelled it
99```
100
101## Server
102
103```objc
104MPMessagePackServer *server = [[MPMessagePackServer alloc] initWithOptions:MPMessagePackOptionsFramed];
105
106server.requestHandler = ^(NSString *method, id params, MPRequestCompletion completion) {
107  if ([method isEqualToString:@"echo"]) {
108    completion(nil, params);
109  } else {
110    completion(@{@"error": {@"description": @"Method not found"}}, nil);
111  }
112};
113
114NSError *error = nil;
115if (![server openWithPort:93434 error:&error]) {
116  // Failed to open
117}
118```
119
120## Mantle Encoding
121
122If you are using Mantle to encode objects to JSON (and then msgpack), you can specify a coder for the MPMessagePackClient:
123
124```objc
125@interface KBMantleCoder : NSObject <MPMessagePackCoder>
126@end
127
128@implementation KBMantleCoder
129- (NSDictionary *)encodeModel:(id)obj {
130  return [obj conformsToProtocol:@protocol(MTLJSONSerializing)] ? [MTLJSONAdapter JSONDictionaryFromModel:obj] : obj;
131}
132@end
133```
134
135Then in the client:
136
137```objc
138MPMessagePackClient *client = [[MPMessagePackClient alloc] init];
139client.coder = [[KBMantleCoder alloc] init];
140```
141
142## XPC
143
144There is an experimental, but functional msgpack-rpc over XPC (see XPC directory). More details soon.
145