--- /dev/null
+//
+// NJMapping.m
+// Enjoy
+//
+// Created by Sam McCall on 4/05/09.
+//
+
+#import "NJMapping.h"
+
+#import "NJInput.h"
+#import "NJOutput.h"
+
+@implementation NJMapping
+
+- (id)initWithName:(NSString *)name {
+ if ((self = [super init])) {
+ self.name = name ? name : @"Untitled";
+ _entries = [[NSMutableDictionary alloc] init];
+ }
+ return self;
+}
+
+- (NJOutput *)objectForKeyedSubscript:(NJInput *)input {
+ return input ? _entries[input.uid] : nil;
+}
+
+- (void)setObject:(NJOutput *)output forKeyedSubscript:(NJInput *)input {
+ if (input) {
+ if (output)
+ _entries[input.uid] = output;
+ else
+ [_entries removeObjectForKey:input.uid];
+ }
+}
+
+- (NSDictionary *)serialize {
+ NSMutableDictionary *entries = [[NSMutableDictionary alloc] initWithCapacity:_entries.count];
+ for (id key in _entries) {
+ id serialized = [_entries[key] serialize];
+ if (serialized)
+ entries[key] = serialized;
+ }
+ return @{ @"name": _name, @"entries": entries };
+}
+
+- (BOOL)writeToURL:(NSURL *)url error:(NSError **)error {
+ [NSProcessInfo.processInfo disableSuddenTermination];
+ NSDictionary *serialization = [self serialize];
+ NSData *json = [NSJSONSerialization dataWithJSONObject:serialization
+ options:NSJSONWritingPrettyPrinted
+ error:error];
+ BOOL success = json && [json writeToURL:url options:NSDataWritingAtomic error:error];
+ [NSProcessInfo.processInfo enableSuddenTermination];
+ return success;
+}
+
++ (id)mappingWithContentsOfURL:(NSURL *)url mappings:(NSArray *)mappings error:(NSError **)error {
+ NSInputStream *stream = [NSInputStream inputStreamWithURL:url];
+ [stream open];
+ NSDictionary *serialization = stream && !*error
+ ? [NSJSONSerialization JSONObjectWithStream:stream options:0 error:error]
+ : nil;
+ [stream close];
+
+ if (!serialization && error)
+ return nil;
+
+ if (!([serialization isKindOfClass:NSDictionary.class]
+ && [serialization[@"name"] isKindOfClass:NSString.class]
+ && [serialization[@"entries"] isKindOfClass:NSDictionary.class])) {
+ *error = [NSError errorWithDomain:@"Enjoyable"
+ code:0
+ description:@"This isn't a valid mapping file."];
+ return nil;
+ }
+
+ NSDictionary *entries = serialization[@"entries"];
+ NJMapping *mapping = [[NJMapping alloc] initWithName:serialization[@"name"]];
+ for (id key in entries) {
+ NSDictionary *value = entries[key];
+ if ([key isKindOfClass:NSString.class]) {
+ NJOutput *output = [NJOutput outputDeserialize:value
+ withMappings:mappings];
+ if (output)
+ mapping.entries[key] = output;
+ }
+ }
+ return mapping;
+}
+
+@end