     
     /// Format an unboxed value into another value (or nil if the formatting failed)
     func format(unboxedValue: UnboxRawValueType) -> UnboxFormattedType?
+}
+
+// MARK: - Default protocol implementations
+
+public extension UnboxableRawType {
+    static func unbox(value: Any) throws -> Self? {
+        if let matchedValue = value as? Self {
+            return matchedValue
+        }
+        
+        if let string = value as? String {
+            return self.transform(unboxedString: string)
+        }
+
+        if let int = value as? Int {
+            return self.transform(unboxedInt: int)
+        }
+
+        return nil
+    }
+}
+
+public extension UnboxableByTransform {
+    static func unbox(value: Any) throws -> Self? {
+        guard let rawValue = value as? UnboxRawValueType else {
+            return nil
+        }
+        
+        return self.transform(unboxedValue: rawValue)
+    }
+}
+
+public extension UnboxableEnum {
+    static func unbox(value: Any) throws -> Self? {
+        guard let rawValue = value as? RawValue else {
+            return nil
+        }
+        
+        return self.init(rawValue: rawValue)
+    }
 }
 
 // MARK: - Extensions

    
    /// Perform custom unboxing on an array of dictionaries, executing a closure with a new Unboxer for each one, or throw an UnboxError
    public static func performCustomUnboxing<T>(array: [UnboxableDictionary], context: Any? = nil, allowInvalidElements: Bool = false, closure: (Unboxer) throws -> T?) throws -> [T] {
        
        if allowInvalidElements {
            return array.flatMap { (dictionary) -> T? in
                return try? self.performCustomUnboxing(dictionary: dictionary, context: context, closure: closure)

}

/// Protocol used to enable any type as being unboxable with a certain formatter type
public protocol UnboxableWithFormatter {
    /// The type of formatter to use to format an unboxed value into a value of this type
    associatedtype UnboxFormatterType: UnboxFormatter
}
