Merge pull request #885 from amosavian/master

diff --git a/Docs/Status.md b/Docs/Status.md
index 7a27e3c..d201633 100644
--- a/Docs/Status.md
+++ b/Docs/Status.md
@@ -196,7 +196,7 @@
 
     | Entity Name                 | Status          | Test Coverage | Notes                                                                                                                                                            |
     |-----------------------------|-----------------|---------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-    | `RegularExpression`         | Mostly Complete | Substantial   | `NSCoding` remains unimplemented                                                                                                                                 |
+    | `NSRegularExpression`       | Complete        | Substantial   |                                                                                                                                 |
     | `Scanner`                   | Mostly Complete | Incomplete    | `scanHex<T: _FloatLike>(_:locale:locationToScanFrom:to:)` and `localizedScannerWithString(_:)` remain unimplemented                                              |
     | `NSTextCheckingResult`      | Mostly Complete | Incomplete    | `NSCoding`, `NSCopying`, `resultType`, and `range(at:)` remain unimplemented                                                                                     |
     | `NSAttributedString`        | Incomplete      | Incomplete    | `NSCoding`, `NS[Mutable]Copying`, `attributedSubstring(from:)`, `isEqual(to:)`, `init(NSAttributedString:)` remain unimplemented |
diff --git a/Foundation/NSRegularExpression.swift b/Foundation/NSRegularExpression.swift
index fca86c1..0d1a289 100644
--- a/Foundation/NSRegularExpression.swift
+++ b/Foundation/NSRegularExpression.swift
@@ -39,11 +39,37 @@
     }
     
     open func encode(with aCoder: NSCoder) {
-        NSUnimplemented()
+        guard aCoder.allowsKeyedCoding else {
+            preconditionFailure("Unkeyed coding is unsupported.")
+        }
+        
+        aCoder.encode(self.pattern._nsObject, forKey: "NSPattern")
+        aCoder.encode(self.options.rawValue._bridgeToObjectiveC(), forKey: "NSOptions")
     }
     
-    public required init?(coder aDecoder: NSCoder) {
-        NSUnimplemented()
+    public required convenience init?(coder aDecoder: NSCoder) {
+        guard aDecoder.allowsKeyedCoding else {
+            preconditionFailure("Unkeyed coding is unsupported.")
+        }
+        
+        guard let pattern = aDecoder.decodeObject(forKey: "NSPattern") as? NSString,
+            let options = aDecoder.decodeObject(forKey: "NSOptions") as? NSNumber else {
+                return nil
+        }
+        
+        do {
+            try self.init(pattern: pattern._swiftObject, options: Options(rawValue: options.uintValue))
+        } catch {
+            return nil
+        }
+    }
+    
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? NSRegularExpression else { return false }
+        
+        return self === other
+            || (self.pattern == other.pattern
+                && self.options == other.options)
     }
     
     /* An instance of NSRegularExpression is created from a regular expression pattern and a set of options.  If the pattern is invalid, nil will be returned and an NSError will be returned by reference.  The pattern syntax currently supported is that specified by ICU.
diff --git a/TestFoundation/TestNSRegularExpression.swift b/TestFoundation/TestNSRegularExpression.swift
index 9e18a92..5e5eb77 100644
--- a/TestFoundation/TestNSRegularExpression.swift
+++ b/TestFoundation/TestNSRegularExpression.swift
@@ -25,7 +25,9 @@
         return [
             ("test_simpleRegularExpressions", test_simpleRegularExpressions),
             ("test_regularExpressionReplacement", test_regularExpressionReplacement),
-            ("test_complexRegularExpressions", test_complexRegularExpressions)
+            ("test_complexRegularExpressions", test_complexRegularExpressions),
+            ("test_Equal", test_Equal),
+            ("test_NSCoding", test_NSCoding),
         ]
     }
     
@@ -317,4 +319,37 @@
         complexRegularExpressionTest("(a|b)x|123|(c|d)y", [], "axcy", [], NSMakeRange(0, 4), 2, NSMakeRange(0, 2), NSMakeRange(0, 1), NSMakeRange(NSNotFound, 0))
         complexRegularExpressionTest("(a|b)x|123|(c|d)y", [], "cya", [], NSMakeRange(0, 3), 1, NSMakeRange(0, 2), NSMakeRange(NSNotFound, 0), NSMakeRange(0, 1))
     }
+    
+    func test_Equal() {
+        var regularExpressionA = try! NSRegularExpression(pattern: "[a-z]+", options: [])
+        var regularExpressionB = try! NSRegularExpression(pattern: "[a-z]+", options: [])
+        XCTAssertTrue(regularExpressionA == regularExpressionB)
+        XCTAssertFalse(regularExpressionA === regularExpressionB)
+        
+        regularExpressionA = try! NSRegularExpression(pattern: "[a-z]+", options: .caseInsensitive)
+        regularExpressionB = try! NSRegularExpression(pattern: "[a-z]+", options: .caseInsensitive)
+        XCTAssertTrue(regularExpressionA == regularExpressionB)
+        XCTAssertFalse(regularExpressionA === regularExpressionB)
+        
+        regularExpressionA = try! NSRegularExpression(pattern: "[a-z]+", options: [.caseInsensitive, .allowCommentsAndWhitespace])
+        regularExpressionB = try! NSRegularExpression(pattern: "[a-z]+", options: [.caseInsensitive, .allowCommentsAndWhitespace])
+        XCTAssertTrue(regularExpressionA == regularExpressionB)
+        XCTAssertFalse(regularExpressionA === regularExpressionB)
+        
+        regularExpressionA = try! NSRegularExpression(pattern: "[a-z]+", options: .caseInsensitive)
+        regularExpressionB = try! NSRegularExpression(pattern: "[a-z]+", options: [.caseInsensitive, .allowCommentsAndWhitespace])
+        XCTAssertFalse(regularExpressionA == regularExpressionB)
+        XCTAssertFalse(regularExpressionA === regularExpressionB)
+        
+        regularExpressionA = try! NSRegularExpression(pattern: "[a-y]+", options: .caseInsensitive)
+        regularExpressionB = try! NSRegularExpression(pattern: "[a-z]+", options: .caseInsensitive)
+        XCTAssertFalse(regularExpressionA == regularExpressionB)
+        XCTAssertFalse(regularExpressionA === regularExpressionB)
+    }
+    
+    func test_NSCoding() {
+        let regularExpressionA = try! NSRegularExpression(pattern: "[a-z]+", options: [.caseInsensitive, .allowCommentsAndWhitespace])
+        let regularExpressionB = NSKeyedUnarchiver.unarchiveObject(with: NSKeyedArchiver.archivedData(withRootObject: regularExpressionA)) as! NSRegularExpression
+        XCTAssertEqual(regularExpressionA, regularExpressionB, "Archived then unarchived `NSRegularExpression` must be equal.")
+    }
 }