An alternative Swift method to PHP `pack()` method

Hello everyone

I am looking for an alternative Swift method to PHP pack() 

method to return the same value for this code line

echo pack('H*', sprintf("%02X",1));

Based on w3schools

echo base64_encode(pack('H*', sprintf("%02X",1)));

prints AQ== and

echo base64_encode(sprintf("%02X",1));

prints MDE=

Answered by AhmadAbdul-jawad in 695835022

I made some changes to @OOPer class and it worked for me.

public class MyTag {

    public let tag: UInt8

    public let value: String

    public init(tag: UInt8, value: String) {

        self.tag = tag

        assert(value.utf8.count < 256, "The length of `value` needs to be less than 256.")

        self.value = value

    }

    public var length: UInt8 { UInt8(value.utf8.count) }

    public var tlv: [UInt8] { return ([tag, length] + [UInt8](value.utf8)) }

} 

Thank you @OOPer for your help!

I don't know of such method in Swift.

If you have just a few formats to support, writing yourself should not be too complex.

But the full implementation is certainly more arduous (AFAIK, PHP has not yet covered all the perl spec).

Thank you @Claude31 for your reply

The point is I am looking to implement a feature in Swift to simulate the same feature in a PHP library

and to do the job, I need an alternative Swift method to PHP pack() method

I found an accepted answer here for the same issue in Objective-C but I only need to convert the returned data type NSData to a binary string in Swift. Can you check this accepted answer? [(https://stackoverflow.com/a/8950667/7262400)]

This is what I would write if I were given the PHP class Tag in your link:

import Foundation

public class MyTag {
    public let tag: UInt8
    public let value: String
    
    public init(tag: UInt8, value: String) {
        self.tag = tag
        assert(value.utf8.count < 256, "The length of `value` needs to be less than 256.")
        self.value = value
    }
    
    public var length: Int {
        value.utf8.count
    }

    ///Use this instead of `__toString()`.
    ///Please remember, in PHP, `__toString()` may be called implicitly in many cases.
    ///You may need to replace all such cases to use this `getData()` explicitly.
    public func getData() -> Data {
        return toByteData(tag)
        + toByteData(UInt8(length))
        + value.data(using: .utf8)!
    }
    
    ///Use this instead of `toHex()`.
    func toByteData(_ value: UInt8) -> Data {
        return Data([value])
    }
}

Generally, it is hard to convert code of some language having a concept of binary string into Swift.

You may have two ways:

  • Use String and consider how you embed binary data into String.
  • Use Data and when you need to concatenate it with String, convert the String to Data before concatenating.

I would choose the latter.


let myTag = MyTag(tag: 1, value: "abc")

print(myTag.toByteData(1).base64EncodedString())
//-> AQ==
Accepted Answer

I made some changes to @OOPer class and it worked for me.

public class MyTag {

    public let tag: UInt8

    public let value: String

    public init(tag: UInt8, value: String) {

        self.tag = tag

        assert(value.utf8.count < 256, "The length of `value` needs to be less than 256.")

        self.value = value

    }

    public var length: UInt8 { UInt8(value.utf8.count) }

    public var tlv: [UInt8] { return ([tag, length] + [UInt8](value.utf8)) }

} 

Thank you @OOPer for your help!

An alternative Swift method to PHP `pack()` method
 
 
Q