How to use CommonCrypto for PBKDF2 in Swift 2 & 3 - swift2

I am trying to use CommonCrypto to hash passwords using PBKDF2 in Swift 2 because of its high performance and also due to it being open source
I've already managed to get CommonCrypto working in Swift using module maps but can someone tell me the code for hashing with PBKDF2 in Swift 2 using CommonCrypto

func pbkdf2(hash :CCPBKDFAlgorithm, password: String, salt: [UInt8], keyCount: Int, rounds: UInt32!) -> [UInt8]! {
let derivedKey = [UInt8](count:keyCount, repeatedValue:0)
let passwordData = password.dataUsingEncoding(NSUTF8StringEncoding)!
let derivationStatus = CCKeyDerivationPBKDF(
CCPBKDFAlgorithm(kCCPBKDF2),
UnsafePointer<Int8>(passwordData.bytes), passwordData.length,
UnsafePointer<UInt8>(salt), salt.count,
CCPseudoRandomAlgorithm(hash),
rounds,
UnsafeMutablePointer<UInt8>(derivedKey),
derivedKey.count)
if (derivationStatus != 0) {
print("Error: \(derivationStatus)")
return nil;
}
return derivedKey
}
hash is the hash type such as kCCPRFHmacAlgSHA1, kCCPRFHmacAlgSHA256, kCCPRFHmacAlgSHA512.
Example from sunsetted documentation section:
Password Based Key Derivation 2 (Swift 3+)
Password Based Key Derivation can be used both for deriving an encryption key from password text and saving a password for authentication purposes.
There are several hash algorithms that can be used including SHA1, SHA256, SHA512 which are provided by this example code.
The rounds parameter is used to make the calculation slow so that an attacker will have to spend substantial time on each attempt. Typical delay values fall in the 100ms to 500ms, shorter values can be used if there is unacceptable performance.
This example requires Common Crypto
It is necessary to have a bridging header to the project:
#import <CommonCrypto/CommonCrypto.h>
Add the Security.framework to the project.
Parameters:
password password String
salt salt Data
keyByteCount number of key bytes to generate
rounds Iteration rounds
returns Derived key
func pbkdf2SHA1(password: String, salt: Data, keyByteCount: Int, rounds: Int) -> Data? {
return pbkdf2(hash:CCPBKDFAlgorithm(kCCPRFHmacAlgSHA1), password:password, salt:salt, keyByteCount:keyByteCount, rounds:rounds)
}
func pbkdf2SHA256(password: String, salt: Data, keyByteCount: Int, rounds: Int) -> Data? {
return pbkdf2(hash:CCPBKDFAlgorithm(kCCPRFHmacAlgSHA256), password:password, salt:salt, keyByteCount:keyByteCount, rounds:rounds)
}
func pbkdf2SHA512(password: String, salt: Data, keyByteCount: Int, rounds: Int) -> Data? {
return pbkdf2(hash:CCPBKDFAlgorithm(kCCPRFHmacAlgSHA512), password:password, salt:salt, keyByteCount:keyByteCount, rounds:rounds)
}
func pbkdf2(hash :CCPBKDFAlgorithm, password: String, salt: Data, keyByteCount: Int, rounds: Int) -> Data? {
let passwordData = password.data(using:String.Encoding.utf8)!
var derivedKeyData = Data(repeating:0, count:keyByteCount)
let derivationStatus = derivedKeyData.withUnsafeMutableBytes {derivedKeyBytes in
salt.withUnsafeBytes { saltBytes in
CCKeyDerivationPBKDF(
CCPBKDFAlgorithm(kCCPBKDF2),
password, passwordData.count,
saltBytes, salt.count,
hash,
UInt32(rounds),
derivedKeyBytes, derivedKeyData.count)
}
}
if (derivationStatus != 0) {
print("Error: \(derivationStatus)")
return nil;
}
return derivedKeyData
}
Example usage:
let password = "password"
//let salt = "saltData".data(using: String.Encoding.utf8)!
let salt = Data(bytes: [0x73, 0x61, 0x6c, 0x74, 0x44, 0x61, 0x74, 0x61])
let keyByteCount = 16
let rounds = 100000
let derivedKey = pbkdf2SHA1(password:password, salt:salt, keyByteCount:keyByteCount, rounds:rounds)
print("derivedKey (SHA1): \(derivedKey! as NSData)")
Example Output:
derivedKey (SHA1): <6b9d4fa3 0385d128 f6d196ee 3f1d6dbf>
Password Based Key Derivation Calibration
This example requires Common Crypto
It is necessary to have a bridging header to the project:
#import <CommonCrypto/CommonCrypto.h>
Add the Security.framework to the project.
Determine the number of PRF rounds to use for a specific delay on the current platform.
Several parameters are defaulted to representative values that should not materially affect the round count.
password Sample password.
salt Sample salt.
msec Targeted duration we want to achieve for a key derivation.
returns The number of iterations to use for the desired processing time.
Password Based Key Derivation Calibration (Swift 3)
func pbkdf2SHA1Calibrate(password: String, salt: Data, msec: Int) -> UInt32 {
let actualRoundCount: UInt32 = CCCalibratePBKDF(
CCPBKDFAlgorithm(kCCPBKDF2),
password.utf8.count,
salt.count,
CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA1),
kCCKeySizeAES256,
UInt32(msec));
return actualRoundCount
}
Example usage:
let saltData = Data(bytes: [0x73, 0x61, 0x6c, 0x74, 0x44, 0x61, 0x74, 0x61])
let passwordString = "password"
let delayMsec = 100
let rounds = pbkdf2SHA1Calibrate(password:passwordString, salt:saltData, msec:delayMsec)
print("For \(delayMsec) msec delay, rounds: \(rounds)")
Example Output:
For 100 msec delay, rounds: 93457
Password Based Key Derivation Calibration (Swift 2.3)
func pbkdf2SHA1Calibrate(password:String, salt:[UInt8], msec:Int) -> UInt32 {
let actualRoundCount: UInt32 = CCCalibratePBKDF(
CCPBKDFAlgorithm(kCCPBKDF2),
password.utf8.count,
salt.count,
CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA1),
kCCKeySizeAES256,
UInt32(msec));
return actualRoundCount
}
Example usage:
let saltData = [UInt8]([0x73, 0x61, 0x6c, 0x74, 0x44, 0x61, 0x74, 0x61])
let passwordString = "password"
let delayMsec = 100
let rounds = pbkdf2SHA1Calibrate(passwordString, salt:saltData, msec:delayMsec)
print("For \(delayMsec) msec delay, rounds: \(rounds)")

For Swift 4 working code would be
func pbkdf2(hash: CCPBKDFAlgorithm, password: String, salt: String, keyByteCount: Int, rounds: Int) -> Data? {
guard let passwordData = password.data(using: .utf8), let saltData = salt.data(using: .utf8) else { return nil }
var derivedKeyData = Data(repeating: 0, count: keyByteCount)
let derivedCount = derivedKeyData.count
let derivationStatus = derivedKeyData.withUnsafeMutableBytes { derivedKeyBytes in
saltData.withUnsafeBytes { saltBytes in
CCKeyDerivationPBKDF(
CCPBKDFAlgorithm(kCCPBKDF2),
password,
passwordData.count,
saltBytes,
saltData.count,
hash,
UInt32(rounds),
derivedKeyBytes,
derivedCount)
}
}
return derivationStatus == kCCSuccess ? derivedKeyData : nil
}

Here is a working Swift 5 example, got rid of all compiler warnings:
private func pbkdf2(password: String, saltData: Data, keyByteCount: Int, prf: CCPseudoRandomAlgorithm, rounds: Int) -> Data? {
guard let passwordData = password.data(using: .utf8) else { return nil }
var derivedKeyData = Data(repeating: 0, count: keyByteCount)
let derivedCount = derivedKeyData.count
let derivationStatus: Int32 = derivedKeyData.withUnsafeMutableBytes { derivedKeyBytes in
let keyBuffer: UnsafeMutablePointer<UInt8> =
derivedKeyBytes.baseAddress!.assumingMemoryBound(to: UInt8.self)
return saltData.withUnsafeBytes { saltBytes -> Int32 in
let saltBuffer: UnsafePointer<UInt8> = saltBytes.baseAddress!.assumingMemoryBound(to: UInt8.self)
return CCKeyDerivationPBKDF(
CCPBKDFAlgorithm(kCCPBKDF2),
password,
passwordData.count,
saltBuffer,
saltData.count,
prf,
UInt32(rounds),
keyBuffer,
derivedCount)
}
}
return derivationStatus == kCCSuccess ? derivedKeyData : nil
}

Related

What is the Rust equivalent to append in Go?

I am trying to figure out on my own reading through documentation, but with no luck on how to convert this Go function into Rust:
func main() {
cards := []string{"Ace of Diamonds", newCard()}
cards = append(cards, "Six of Spades")
fmt.Println(cards)
}
func newCard() string {
return "Five of Diamonds"
}
This is not correct, at least the cards.append I know is wrong:
fn main() {
let mut cards: [&str; 2] = ["Ace of Diamonds", new_card()];
let mut additional_card: [&str; 1] = ["Six of Spades"];
cards.append(additional_card);
println!("cards")
}
fn new_card() -> &'static str {
"Five of Diamonds"
}
You can't. like in Go, Rust arrays are fixed size.
The type [&str; 2] in Rust is roughly equivalent to [2]string in Go, which you also can't append to.
The closest to a Go slice you can get to in Rust is a Vec which you can use like this:
fn main() {
let mut cards = vec!["Ace of Diamonds", new_card()];
let additional_cards: [&str; 2] = ["Six of Spades", "Seven of Clubs"];
// for anything that implements `IntoIter` of cards
cards.extend(additional_cards);
// or for a single card only
cards.push("Three of Hearts");
println!("{cards:?}")
}
fn new_card() -> &'static str {
"Five of Diamonds"
}

Using bitsets in golang to represent capabilities

I am new to Golang and would like to model physical devices for measuring quantities such as light intensity, mass, electric current and so forth. So as a starting point I will define a device struct as follows:
const (
// Light can be measured in the form of luminosity
Light = 1<< iota
Mass
ElectricalCurrent
)
type PhysicalDevice struct{
Owner string
ID string
Description string
}
I am a confused now on how to express the device's capabilities (what it can measure) and the units of measurement. For example I would like to express that a physical device can measure electrical currents in amperes. However, I also want to express that a PhysicalDevice can measure more than one quantity. For example it could measure electrical current and temperature.
The PhysicalDevice's capabilities are not known in advance and can contain an arbitrary combination of capabilities.
I was thinking of using something equivalent to a C++ bitset for expressing the physical quantities a device can measure (would this be the right approach in the first place?).
I did not find the Go bitset type and not sure how to express that. I also need to map the measured physical quantity to a corresponding unit.
You should understand that trying to replicate another language's features in Go is generally regarded as a bad idea. There is a 'go' way of doing things.
You might want to consider iota and bitmask operations like this example on the Go playground. I have included the code here as well (in all its plagiarized glory):
package main
import "fmt"
func main() {
TestAddFlag()
TestHasFlag()
TestClearFlag()
TestToggleFlag()
fmt.Println("all tests passed")
}
type Bitmask uint32
func (f Bitmask) HasFlag(flag Bitmask) bool { return f&flag != 0 }
func (f *Bitmask) AddFlag(flag Bitmask) { *f |= flag }
func (f *Bitmask) ClearFlag(flag Bitmask) { *f &= ^flag }
func (f *Bitmask) ToggleFlag(flag Bitmask) { *f ^= flag }
const (
TESTFLAG_ONE Bitmask = 1 << iota
TESTFLAG_TWO
TESTFLAG_THREE
)
func TestAddFlag() {
var mainFlag Bitmask = TESTFLAG_TWO
mainFlag.AddFlag(TESTFLAG_THREE)
if mainFlag&(1<<TESTFLAG_THREE) != 0 {
panic("failed")
}
}
func TestClearFlag() {
var mainFlag Bitmask = TESTFLAG_ONE | TESTFLAG_THREE
mainFlag.ClearFlag(TESTFLAG_THREE)
if mainFlag&(1<<TESTFLAG_ONE) != 0 {
panic("failed")
}
}
func TestHasFlag() {
var mainFlag Bitmask = TESTFLAG_ONE | TESTFLAG_THREE
if !mainFlag.HasFlag(TESTFLAG_THREE) {
panic("failed")
}
}
func TestToggleFlag() {
flag := TESTFLAG_ONE | TESTFLAG_THREE
flag.ToggleFlag(TESTFLAG_ONE)
if flag.HasFlag(TESTFLAG_ONE) {
panic("failed")
}
flag.ToggleFlag(TESTFLAG_ONE)
if !flag.HasFlag(TESTFLAG_ONE) {
panic("failed")
}
}
This approach is commonly used in the standard library.
Define the capabilities using = 1 << iota:
const (
Light Capability = 1 << iota
Mass
ElectricalCurrent
Energy
)
Notice that the expression is only needed on the first constant. The same expression (but with an updated value of iota) will be used on the consecutive lines in the same group.
Here's a complete working example:
package main
import (
"fmt"
"strings"
)
type Capability int
const (
// Light can be measured in the form of luminosity
Light Capability = 1 << iota
Mass
ElectricalCurrent
Energy
)
func (c Capability) String() string {
var caps []string
if c&Light > 0 {
caps = append(caps, "Light")
}
if c&Mass > 0 {
caps = append(caps, "Mass")
}
if c&ElectricalCurrent > 0 {
caps = append(caps, "ElectricalCurrent")
}
if c&Energy > 0 {
caps = append(caps, "Energy")
}
return strings.Join(caps, "|")
}
type PhysicalDevice struct {
Owner string
ID string
Description string
Capability Capability
}
func (pd PhysicalDevice) String() string {
return "Owner: " + pd.Owner + "\n" +
"ID: " + pd.ID + "\n" +
"Description: " + pd.Description + "\n" +
"Capability: " + pd.Capability.String() + "\n"
}
func main() {
dev := PhysicalDevice{
Owner: "Albert Einstein",
ID: "E=mc^2",
Description: "My well-known formula as a device",
Capability: Energy | Mass | Light,
}
fmt.Println(dev)
}
The code can be found on The Go Playground.

ReadConsoleInputW wrapper and ownership

I want to wrap the ReadConsoleInputW Windows console method into the Read trait so that I can use the chars() method, but I need also to know which key modifiers are applied (control, alt/meta).
One solution (like the one used by the Unix console) is to encode key events into control characters or ANSI escape codes.
Another solution would be to keep the key modifiers around but I can't make it work because the chars() method consume/move the input:
struct InputBuffer {
handle: winapi::HANDLE,
ctrl: bool,
meta: bool,
}
impl Read for InputBuffer {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let mut rec: winapi::INPUT_RECORD = unsafe { mem::zeroed() };
// kernel32::ReadConsoleInputW(self.0, &mut rec, 1 as winapi::DWORD, &mut count);
// ...
if rec.EventType != winapi::KEY_EVENT {
continue;
}
let key_event = unsafe { rec.KeyEvent() };
// ...
self.ctrl = key_event.dwControlKeyState &
(winapi::LEFT_CTRL_PRESSED | winapi::RIGHT_CTRL_PRESSED) ==
(winapi::LEFT_CTRL_PRESSED | winapi::RIGHT_CTRL_PRESSED);
self.meta = ...;
let utf16 = key_event.UnicodeChar;
// ...
let (bytes, len) = try!(InputBuffer::wide_char_to_multi_byte(utf16));
return (&bytes[..len]).read(buf);
}
}
fn main() {
let handle = try!(get_std_handle(STDIN_FILENO));
let mut stdin = InputBuffer(handle);
let mut chars = stdin.chars(); // stdin moved here
loop {
let c = chars.next().unwrap();
let mut ch = try!(c);
if stdin.ctrl { // use of moved value
//...
}
// ...
}
}
How to do this in Rust?
You could put these flags into Rc<RefCell<somestruct>> and clone it before consuming stdin.
This is a common pattern that allows you to have "access" to the same data, from two places. Rc takes care of shared ownership, and RefCell checks if you don't have overlapping accesses.

How to choose a random enumeration value

I am trying to randomly choose an enum value:
enum GeometryClassification {
case Circle
case Square
case Triangle
case GeometryClassificationMax
}
and the random selection:
let shapeGeometry = ( arc4random() % GeometryClassification.GeometryClassificationMax ) as GeometryClassification
but it fails.
I get errors like:
'GeometryClassification' is not convertible to 'UInt32'
How do I solve this?
In Swift there is actually a protocol for enums called CaseIterable that, if you add it to your enum, you can just reference all of the cases as a collection with .allCases as so:
enum GeometryClassification: CaseIterable {
case Circle
case Square
case Triangle
}
and then you can .allCases and then .randomElement() to get a random one
let randomGeometry = GeometryClassification.allCases.randomElement()!
The force unwrapping is required because there is a possibility of an enum having no cases and thus randomElement() would return nil.
Swift has gained new features since this answer was written that provide a much better solution — see "How to choose a random enumeration value" instead.
I'm not crazy about your last case there -- it seems like you're including .GeometryClassificationMax solely to enable random selection. You'll need to account for that extra case everywhere you use a switch statement, and it has no semantic value. Instead, a static method on the enum could determine the maximum value and return a random case, and would be much more understandable and maintainable.
enum GeometryClassification: UInt32 {
case Circle
case Square
case Triangle
private static let _count: GeometryClassification.RawValue = {
// find the maximum enum value
var maxValue: UInt32 = 0
while let _ = GeometryClassification(rawValue: maxValue) {
maxValue += 1
}
return maxValue
}()
static func randomGeometry() -> GeometryClassification {
// pick and return a new value
let rand = arc4random_uniform(_count)
return GeometryClassification(rawValue: rand)!
}
}
And you can now exhaust the enum in a switch statement:
switch GeometryClassification.randomGeometry() {
case .Circle:
println("Circle")
case .Square:
println("Square")
case .Triangle:
println("Triangle")
}
Since you're inside the enum class, having the random() method reference the highest value explicitly would eliminate having to count them every time:
enum GeometryClassification: UInt32 {
case Circle
case Square
case Triangle
static func random() -> GeometryClassification {
// Update as new enumerations are added
let maxValue = Triangle.rawValue
let rand = arc4random_uniform(maxValue+1)
return GeometryClassification(rawValue: rand)!
}
}
For Swift 5 there is "RandomNumberGenerator":
enum Weekday: CaseIterable {
case sunday, monday, tuesday, wednesday, thursday, friday, saturday
static func random<G: RandomNumberGenerator>(using generator: inout G) -> Weekday {
return Weekday.allCases.randomElement(using: &generator)!
}
static func random() -> Weekday {
var g = SystemRandomNumberGenerator()
return Weekday.random(using: &g)
}
}
You need to assign a raw type to your enum. If you use an integer type, then the enumeration case values will be auto-generated starting at 0:
enum GeometryClassification: UInt32 {
case Circle
case Square
case Triangle
case GeometryClassificationMax
}
Per Enumerations:
"Unlike C and Objective-C, Swift enumeration members are not assigned a default integer value when they are created."
Specifying the integer type lets it know to generate the values in the usual way.
Then you can generate the random value like this:
let randomEnum: GeometryClassification = GeometryClassification.fromRaw(arc4random_uniform(GeometryClassification.GeometryClassificationMax.toRaw()))!
This is a horribly ugly call, and all those fromRaw and toRaw calls are fairly inelegant, so I would really recommend generating a random UInt32 that is in the range you want first, then creating a GeometryClassification from that value:
GeometryClassification.fromRaw(someRandomUInt32)
You can put all the values into array and generate random,
extension GeometryClassification {
static func random() -> GeometryClassification {
let all: [GeometryClassification] = [.Circle,
.Square,
.Triangle,
.GeometryClassificationMax]
let randomIndex = Int(arc4random()) % all.count
return all[randomIndex]
}
}
The easiest thing to do is to create a global extension:
extension CaseIterable {
static func randomElement() -> AllCases.Element {
guard Self.allCases.count > 0 else {
fatalError("There must be at least one case in the enum")
}
return Self.allCases.randomElement()!
}
}
This way any enum which conforms to CaseIterable has the function automatically
Here's my Swift 1.2 take:
enum GeometryClassification : Int {
case Circle = 0
case Square = 1
case Triangle = 2
static func random() -> GeometryClassification {
let min = MutationType.Circle.rawValue
let max = MutationType.Triangle.rawValue
let rand = Int.random(min: min, max: max) // Uses ExSwift!
return self(rawValue: rand)!
}
}
I wrote a global extension using Andy's answer. Enjoy :)
extension CaseIterable {
static func random<G: RandomNumberGenerator>(using generator: inout G) -> Self.AllCases.Element {
return Self.allCases.randomElement(using: &generator)!
}
static func random() -> Self.AllCases.Element {
var g = SystemRandomNumberGenerator()
return Self.random(using: &g)
}
}
Just extend your enumeration to conform CaseIterable protocol and use like:
let state = YourEnum.random()

What is an idiomatic way of representing enums in Go?

I'm trying to represent a simplified chromosome, which consists of N bases, each of which can only be one of {A, C, T, G}.
I'd like to formalize the constraints with an enum, but I'm wondering what the most idiomatic way of emulating an enum is in Go.
Quoting from the language specs:Iota
Within a constant declaration, the predeclared identifier iota represents successive untyped integer constants. It is reset to 0 whenever the reserved word const appears in the source and increments after each ConstSpec. It can be used to construct a set of related constants:
const ( // iota is reset to 0
c0 = iota // c0 == 0
c1 = iota // c1 == 1
c2 = iota // c2 == 2
)
const (
a = 1 << iota // a == 1 (iota has been reset)
b = 1 << iota // b == 2
c = 1 << iota // c == 4
)
const (
u = iota * 42 // u == 0 (untyped integer constant)
v float64 = iota * 42 // v == 42.0 (float64 constant)
w = iota * 42 // w == 84 (untyped integer constant)
)
const x = iota // x == 0 (iota has been reset)
const y = iota // y == 0 (iota has been reset)
Within an ExpressionList, the value of each iota is the same because it is only incremented after each ConstSpec:
const (
bit0, mask0 = 1 << iota, 1<<iota - 1 // bit0 == 1, mask0 == 0
bit1, mask1 // bit1 == 2, mask1 == 1
_, _ // skips iota == 2
bit3, mask3 // bit3 == 8, mask3 == 7
)
This last example exploits the implicit repetition of the last non-empty expression list.
So your code might be like
const (
A = iota
C
T
G
)
or
type Base int
const (
A Base = iota
C
T
G
)
if you want bases to be a separate type from int.
Referring to the answer of jnml, you could prevent new instances of Base type by not exporting the Base type at all (i.e. write it lowercase). If needed, you may make an exportable interface that has a method that returns a base type. This interface could be used in functions from the outside that deal with Bases, i.e.
package a
type base int
const (
A base = iota
C
T
G
)
type Baser interface {
Base() base
}
// every base must fulfill the Baser interface
func(b base) Base() base {
return b
}
func(b base) OtherMethod() {
}
package main
import "a"
// func from the outside that handles a.base via a.Baser
// since a.base is not exported, only exported bases that are created within package a may be used, like a.A, a.C, a.T. and a.G
func HandleBasers(b a.Baser) {
base := b.Base()
base.OtherMethod()
}
// func from the outside that returns a.A or a.C, depending of condition
func AorC(condition bool) a.Baser {
if condition {
return a.A
}
return a.C
}
Inside the main package a.Baser is effectively like an enum now.
Only inside the a package you may define new instances.
You can make it so:
type MessageType int32
const (
TEXT MessageType = 0
BINARY MessageType = 1
)
With this code compiler should check type of enum
It's true that the above examples of using const and iota are the most idiomatic ways of representing primitive enums in Go. But what if you're looking for a way to create a more fully-featured enum similar to the type you'd see in another language like Java or Python?
A very simple way to create an object that starts to look and feel like a string enum in Python would be:
package main
import (
"fmt"
)
var Colors = newColorRegistry()
func newColorRegistry() *colorRegistry {
return &colorRegistry{
Red: "red",
Green: "green",
Blue: "blue",
}
}
type colorRegistry struct {
Red string
Green string
Blue string
}
func main() {
fmt.Println(Colors.Red)
}
Suppose you also wanted some utility methods, like Colors.List(), and Colors.Parse("red"). And your colors were more complex and needed to be a struct. Then you might do something a bit like this:
package main
import (
"errors"
"fmt"
)
var Colors = newColorRegistry()
type Color struct {
StringRepresentation string
Hex string
}
func (c *Color) String() string {
return c.StringRepresentation
}
func newColorRegistry() *colorRegistry {
red := &Color{"red", "F00"}
green := &Color{"green", "0F0"}
blue := &Color{"blue", "00F"}
return &colorRegistry{
Red: red,
Green: green,
Blue: blue,
colors: []*Color{red, green, blue},
}
}
type colorRegistry struct {
Red *Color
Green *Color
Blue *Color
colors []*Color
}
func (c *colorRegistry) List() []*Color {
return c.colors
}
func (c *colorRegistry) Parse(s string) (*Color, error) {
for _, color := range c.List() {
if color.String() == s {
return color, nil
}
}
return nil, errors.New("couldn't find it")
}
func main() {
fmt.Printf("%s\n", Colors.List())
}
At that point, sure it works, but you might not like how you have to repetitively define colors. If at this point you'd like to eliminate that, you could use tags on your struct and do some fancy reflecting to set it up, but hopefully this is enough to cover most people.
There is a way with struct namespace.
The benefit is all enum variables are under a specific namespace to avoid pollution.
The issue is that we could only use var not const
type OrderStatusType string
var OrderStatus = struct {
APPROVED OrderStatusType
APPROVAL_PENDING OrderStatusType
REJECTED OrderStatusType
REVISION_PENDING OrderStatusType
}{
APPROVED: "approved",
APPROVAL_PENDING: "approval pending",
REJECTED: "rejected",
REVISION_PENDING: "revision pending",
}
As of Go 1.4, the go generate tool has been introduced together with the stringer command that makes your enum easily debuggable and printable.
I am sure we have a lot of good answers here. But, I just thought of adding the way I have used enumerated types
package main
import "fmt"
type Enum interface {
name() string
ordinal() int
values() *[]string
}
type GenderType uint
const (
MALE = iota
FEMALE
)
var genderTypeStrings = []string{
"MALE",
"FEMALE",
}
func (gt GenderType) name() string {
return genderTypeStrings[gt]
}
func (gt GenderType) ordinal() int {
return int(gt)
}
func (gt GenderType) values() *[]string {
return &genderTypeStrings
}
func main() {
var ds GenderType = MALE
fmt.Printf("The Gender is %s\n", ds.name())
}
This is by far one of the idiomatic ways we could create Enumerated types and use in Go.
Edit:
Adding another way of using constants to enumerate
package main
import (
"fmt"
)
const (
// UNSPECIFIED logs nothing
UNSPECIFIED Level = iota // 0 :
// TRACE logs everything
TRACE // 1
// INFO logs Info, Warnings and Errors
INFO // 2
// WARNING logs Warning and Errors
WARNING // 3
// ERROR just logs Errors
ERROR // 4
)
// Level holds the log level.
type Level int
func SetLogLevel(level Level) {
switch level {
case TRACE:
fmt.Println("trace")
return
case INFO:
fmt.Println("info")
return
case WARNING:
fmt.Println("warning")
return
case ERROR:
fmt.Println("error")
return
default:
fmt.Println("default")
return
}
}
func main() {
SetLogLevel(INFO)
}
For a use case like this, it may be useful to use a string constant so it can be marshaled into a JSON string. In the following example, []Base{A,C,G,T} would get marshaled to ["adenine","cytosine","guanine","thymine"].
type Base string
const (
A Base = "adenine"
C = "cytosine"
G = "guanine"
T = "thymine"
)
When using iota, the values get marshaled into integers. In the following example, []Base{A,C,G,T} would get marshaled to [0,1,2,3].
type Base int
const (
A Base = iota
C
G
T
)
Here's an example comparing both approaches:
https://play.golang.org/p/VvkcWvv-Tvj
Here is an example that will prove useful when there are many enumerations. It uses structures in Golang, and draws upon Object Oriented Principles to tie them all together in a neat little bundle. None of the underlying code will change when a new enumeration is added or deleted. The process is:
Define an enumeration structure for enumeration items: EnumItem. It has an integer and string type.
Define the enumeration as a list of enumeration items: Enum
Build methods for the enumeration. A few have been included:
enum.Name(index int): returns the name for the given index.
enum.Index(name string): returns the name for the given index.
enum.Last(): returns the index and name of the last enumeration
Add your enumeration definitions.
Here is some code:
type EnumItem struct {
index int
name string
}
type Enum struct {
items []EnumItem
}
func (enum Enum) Name(findIndex int) string {
for _, item := range enum.items {
if item.index == findIndex {
return item.name
}
}
return "ID not found"
}
func (enum Enum) Index(findName string) int {
for idx, item := range enum.items {
if findName == item.name {
return idx
}
}
return -1
}
func (enum Enum) Last() (int, string) {
n := len(enum.items)
return n - 1, enum.items[n-1].name
}
var AgentTypes = Enum{[]EnumItem{{0, "StaffMember"}, {1, "Organization"}, {1, "Automated"}}}
var AccountTypes = Enum{[]EnumItem{{0, "Basic"}, {1, "Advanced"}}}
var FlagTypes = Enum{[]EnumItem{{0, "Custom"}, {1, "System"}}}
Refactored https://stackoverflow.com/a/17989915/863651 to make it a bit more readable:
package SampleEnum
type EFoo int
const (
A EFoo = iota
C
T
G
)
type IEFoo interface {
Get() EFoo
}
func(e EFoo) Get() EFoo { // every EFoo must fulfill the IEFoo interface
return e
}
func(e EFoo) otherMethod() { // "private"
//some logic
}
This is a safe way to implement enum in golang:
package main
import (
"fmt"
)
const (
MALE = _gender(1)
FEMALE = _gender(2)
RED = _color("RED")
GREEN = _color("GREEN")
BLUE = _color("BLUE")
)
type Gender interface {
_isGender()
Value() int
}
type _gender int
func (_gender) _isGender() {}
func (_g _gender) Value() int {
return int(_g)
}
type Color interface {
_isColor()
Value() string
}
type _color string
func (_color) _isColor() {}
func (_c _color) Value() string {
return string(_c)
}
func main() {
genders := []Gender{MALE, FEMALE}
colors := []Color{RED, GREEN, BLUE}
fmt.Println("Colors =", colors)
fmt.Println("Genders =", genders)
}
The output:
Colors = [RED GREEN BLUE]
Genders = [1 2]
Also, this is a pretty effective way to store different roles in one location in a byte, where the first value is set to 1, bit shifted by an iota.
package main
import "fmt"
const (
isCaptain = 1 << iota
isTrooper
isMedic
canFlyMars
canFlyJupiter
canFlyMoon
)
func main() {
var roles byte = isCaptain | isMedic | canFlyJupiter
//Prints a binary representation.
fmt.Printf("%b\n", roles)
fmt.Printf("%b\n", isCaptain)
fmt.Printf("%b\n", isTrooper)
fmt.Printf("%b\n", isMedic)
fmt.Printf("Is Captain? %v\n", isCaptain&roles == isCaptain)
fmt.Printf("Is Trooper? %v", isTrooper&roles == isTrooper)
}
I created the enum this way. Suppose we need an enum representing gender. Possible values are Male, Female, Others
package gender
import (
"fmt"
"strings"
)
type Gender struct {
g string
}
var (
Unknown = Gender{}
Male = Gender{g: "male"}
Female = Gender{g: "female"}
Other = Gender{g: "other"}
)
var genders = []Gender{
Unknown,
Male,
Female,
Other,
}
func Parse(code string) (parsed Gender, err error) {
for _, g := range genders {
if g.g == strings.ToLower(code) {
if g == Unknown {
err = fmt.Errorf("unknown gender")
}
parsed = g
return
}
}
parsed = Unknown
err = fmt.Errorf("unknown gender", code)
return
}
func (g Gender) Gender() string {
return g.g
}
A simpler way I have found to work.
const (
Stake TX = iota
Withdraw)
type TX int
func (t TX) String() string {
return [...]string{"STAKE", "WITHDRAW"}[t]}
log.Println(Stake.String()) --> STAKE

Resources