I understand that Swift tuples cannot be indexed at runtime. However, I'm working with the POSIX terminal interface (defined by <termios.h>
, which is part of libc).
In the C code, we are able to modify the state of the terminal by doing stuff like this:
termios_struct.c_cc[VMIN] = 0;
termios_struct.c_cc[VTIME] = 0;
Translating that to Swift raises an error, complaining that it cannot access element using subscript for tuple type '(cc_t, cc_t, cc_t ...)' (aka '(UInt8, UInt8, UInt8 ...)')
. The actual tuples have about twenty elements, all UInt8
.
I guess I could just print the values of VMIN
and VTIME
(constants defined by <termios.h>
), then use their values to directly index the tuples, but I'm not sure their values are consistent across platforms, and it's just generally hacky.
What's the proper way to handle this situation?
Edit: This issue is addressed by this answer to another question, named Using termios
in Swift.
Using the answer you referenced as a guide, I came up with the following extension that seems to work.
extension termios {
subscript(c_cc index: Int32) -> cc_t {
get {
var settings = self
var res: cc_t = 0
withUnsafePointer(to: &settings.c_cc) { (tuplePtr) -> Void in
tuplePtr.withMemoryRebound(to: cc_t.self, capacity: MemoryLayout.size(ofValue: self.c_cc)) {
res = $0[Int(index)]
}
}
return res
}
set {
var settings = self
withUnsafeMutablePointer(to: &self.c_cc) { (tuplePtr) -> Void in
tuplePtr.withMemoryRebound(to: cc_t.self, capacity: MemoryLayout.size(ofValue: settings.c_cc)) {
$0[Int(index)] = newValue
}
}
}
}
}
Here's some sample code:
var settings = termios()
print(settings.c_cc)
settings[c_cc: VMIN] = 1
print(settings.c_cc)
print(settings[c_cc: VMIN])
which outputs:
(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0)
1