Swift: Deconstruct SPF: asMechanism with Qualifier
Tags: swift, beginners, package, spf
Published: 2021-05-31 07:15:48

Hi,

In this article, I will walk through how I re-implemented the `enum` for `Qualifier` and `MechanismKind`. I will also deliver a working `asMechanism()` function. The diff is [here](https://github.com/Bas-Man/swift-decon-spf/compare/Initial-asMechanism...QualifierSuppportAsMechanism)

## Enum Qualifier and MechanismKind

I reworked these to make them more self documenting and to also simplify the `get` function. This function could be refactored out.

### Code
```swift
enum Qualifier: String {
    case Pass = "+";
    case Fail = "-";
    case SoftFail = "~";
    case Neutral = "?";
    case None = "";
    
    func get() -> String {
        return self.rawValue;
    }
}
enum MechanismKind: String {
    case Redirect = "redirect=";
    case Include = "include:"
    case A = "a";
    case MX = "mx";
    case Ip4 = "ip4:";
    case Ip6 = "ip6:"
    case All = "all";
    
    func get() -> String {
        return self.rawValue;
    }
}
```
Here we can see I have provided each enum **case** with a new `rawValue` and that the `get` function has been greatly simplified as there is no need for a *switch* statement. These raw values will be used by `asMechanism` to build the string which it returns.

## asMechanism

The `asMechanism` function now has the ability to access the `rawValue` of `kind` and `qualifier` through their member functions `get`.

### Code
```swift
func asMechanism() -> String {
    var mechanismString = String();
    mechanismString += self.qualifier.get();
    // Access the string for this mechanism's kind.
    mechanismString += self.kind.get();
    // Access the string for the mechanism
    mechanismString += self.mechanism;
    return mechanismString;
}
```

### Testing asMechanism

I will list a few examples here.

```swift
func testAsMechanismIp4() {
    let Mech = Mechanism(k: MechanismKind.Ip4, q: Qualifier.None, m: "192.168.1.0/24");
    XCTAssertEqual(Mech.asMechanism(), "ip4:192.168.1.0/24");
}
func testAsMechanismIp4Pass() {
    let Mech = Mechanism(k: MechanismKind.Ip4, q: Qualifier.Pass, m: "192.168.1.0/24");
    XCTAssertEqual(Mech.asMechanism(), "+ip4:192.168.1.0/24");
}

func testAsMechanismIp6() {
    let Mech = Mechanism(k: MechanismKind.Ip6, q: Qualifier.None, m: "X:X:X:X/16");
    XCTAssertEqual(Mech.asMechanism(), "ip6:X:X:X:X/16");
}
func testAsMechanismRedirect() {
    let Mech = Mechanism(k: MechanismKind.Redirect, q: Qualifier.None, m: "_spf.example.com");
    XCTAssertEqual(Mech.asMechanism(), "redirect=_spf.example.com");
}
func testAsMechanismInclude() {
    let Mech = Mechanism(k: MechanismKind.Include, q: Qualifier.None, m: "_spf1.example.com");
    XCTAssertEqual(Mech.asMechanism(), "include:_spf1.example.com");
}
func testAsMechanismA() {
    let Mech = Mechanism(k: MechanismKind.A, q: Qualifier.None, m: "");
    XCTAssertEqual(Mech.asMechanism(), "a");
}
func testAsMechanismMx() {
    let Mech = Mechanism(k: MechanismKind.MX, q: Qualifier.None, m: "");
    XCTAssertEqual(Mech.asMechanism(), "mx");
}
```
Here is an example output within *Xcode*
![Xcode Test Outpu](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9ofuuy685dlmh7orhn5t.png)  
The Green check marks denote passing tests.

The code for this project can be found [here](https://github.com/Bas-Man/swift-decon-spf).

This is the [diff](https://github.com/Bas-Man/swift-decon-spf/compare/Initial-asMechanism...QualifierSuppportAsMechanism) between *Initial-asMechanism* and *QualifierSuppportAsMechanism*.