Skip to content

Instantly share code, notes, and snippets.

@igor-makarov
Last active April 23, 2022 00:04
Show Gist options
  • Save igor-makarov/f0c1ce3e9b6fe291b81338bd4cabafc3 to your computer and use it in GitHub Desktop.
Save igor-makarov/f0c1ce3e9b6fe291b81338bd4cabafc3 to your computer and use it in GitHub Desktop.

Just trying to see how Rust patterns work in Swift

// from: https://doc.rust-lang.org/beta/embedded-book/static-guarantees/design-contracts.html#type-states
protocol EnabledState {}
protocol DirectionState {}
protocol ModeState {}
struct GpioConfig<IsEnabled: EnabledState, Direction: DirectionState, Mode: ModeState> {
var periph: Int64
init(periph: Int64) {
self.periph = periph
}
}
struct Disabled: EnabledState {}
struct Enabled: EnabledState {}
struct Output: DirectionState {}
struct Input: DirectionState {}
struct PulledLow: ModeState {}
struct PulledHigh: ModeState {}
struct HighZ: ModeState {}
struct DontCare: EnabledState, ModeState, DirectionState {}
/// These functions may be used on any GPIO Pin
extension GpioConfig {
func into_disabled() -> GpioConfig<Disabled, DontCare, DontCare> {
// periph modifications omitted
.init(periph: periph)
}
func into_enabled_input() -> GpioConfig<Enabled, Input, HighZ> {
// periph modifications omitted
.init(periph: periph)
}
func into_enabled_output() -> GpioConfig<Enabled, Output, DontCare> {
// periph modifications omitted
.init(periph: periph)
}
}
extension GpioConfig where IsEnabled == Enabled, Direction == Output, Mode == DontCare {
mutating func set_bit(_ set_high: Bool) {
// periph modifications omitted
}
}
extension GpioConfig where IsEnabled == Enabled, Direction == Input {
func bit_is_set() -> Bool {
// periph read omitted
true
}
func into_input_high_z() -> GpioConfig<Enabled, Input, HighZ> {
// periph modifications omitted
.init(periph: periph)
}
func into_input_pull_down() -> GpioConfig<Enabled, Input, PulledLow> {
// periph modifications omitted
.init(periph: periph)
}
func into_input_pull_up() -> GpioConfig<Enabled, Input, PulledHigh> {
// periph modifications omitted
.init(periph: periph)
}
}
func get_gpio() -> GpioConfig<DontCare, DontCare, DontCare> {
// periph code omitted
.init(periph: 0)
}
/*
* Example 1: Unconfigured to High-Z input
*/
let pin = get_gpio()
// Can't do this, pin isn't enabled!
// pin.into_input_pull_down();
// Now turn the pin from unconfigured to a high-z input
let input_pin = pin.into_enabled_input()
// Read from the pin
print("pin_state:", input_pin.bit_is_set())
// Can't do this, input pins don't have this interface!
// input_pin.set_bit(true)
/*
* Example 2: High-Z input to Pulled Low input
*/
let pulled_low = input_pin.into_input_pull_down()
print("pin_state:", pulled_low.bit_is_set())
/*
* Example 3: Pulled Low input to Output, set high
*/
var output_pin = pulled_low.into_enabled_output()
output_pin.set_bit(true)
// Can't do this, output pins don't have this interface!
// output_pin.into_input_pull_down()
print("size:", MemoryLayout.size(ofValue: output_pin)) // 8
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment