libinput-rs 0.3.10

100% drop-in Rust replacement for the libinput 1.31.3 C ABI and tools
Documentation
module resource_lifecycle_model
  implicit none
  private

  integer, parameter :: descriptor_absent = 0
  integer, parameter :: descriptor_open = 1
  integer, parameter :: descriptor_closed = 2
  integer, parameter, public :: backend_path = 1
  integer, parameter, public :: backend_udev = 2

  type, public :: restricted_descriptor
    private
    integer :: state = descriptor_absent
    integer :: close_count = 0
  end type restricted_descriptor

  type, public :: hotplug_permission
    private
    logical :: active = .false.
  end type hotplug_permission

  public :: acquire_descriptor, reject_descriptor, remove_descriptor
  public :: descriptor_is_closed, descriptor_closes
  public :: enable_hotplug, disable_hotplug, hotplug_is_active

contains

  logical function acquire_descriptor(descriptor) result(acquired)
    type(restricted_descriptor), intent(inout) :: descriptor
    acquired = descriptor%state /= descriptor_open
    if (acquired) descriptor%state = descriptor_open
  end function acquire_descriptor

  logical function close_descriptor(descriptor) result(closed)
    type(restricted_descriptor), intent(inout) :: descriptor
    closed = descriptor%state == descriptor_open
    if (closed) then
      descriptor%state = descriptor_closed
      descriptor%close_count = descriptor%close_count + 1
    end if
  end function close_descriptor

  logical function reject_descriptor(descriptor) result(closed)
    type(restricted_descriptor), intent(inout) :: descriptor
    closed = close_descriptor(descriptor)
  end function reject_descriptor

  logical function remove_descriptor(descriptor) result(closed)
    type(restricted_descriptor), intent(inout) :: descriptor
    closed = close_descriptor(descriptor)
  end function remove_descriptor

  pure logical function descriptor_is_closed(descriptor) result(closed)
    type(restricted_descriptor), intent(in) :: descriptor
    closed = descriptor%state == descriptor_closed
  end function descriptor_is_closed

  pure integer function descriptor_closes(descriptor) result(count)
    type(restricted_descriptor), intent(in) :: descriptor
    count = descriptor%close_count
  end function descriptor_closes

  logical function enable_hotplug(backend, permission) result(enabled)
    integer, intent(in) :: backend
    type(hotplug_permission), intent(inout) :: permission
    enabled = backend == backend_udev .and. .not. permission%active
    if (enabled) permission%active = .true.
  end function enable_hotplug

  logical function disable_hotplug(permission) result(disabled)
    type(hotplug_permission), intent(inout) :: permission
    disabled = permission%active
    if (disabled) permission%active = .false.
  end function disable_hotplug

  pure logical function hotplug_is_active(permission) result(active)
    type(hotplug_permission), intent(in) :: permission
    active = permission%active
  end function hotplug_is_active

end module resource_lifecycle_model

program verify_resource_lifecycle
  use resource_lifecycle_model
  implicit none

  type(restricted_descriptor) :: descriptor
  type(hotplug_permission) :: permission
  logical :: changed

  changed = acquire_descriptor(descriptor)
  if (.not. changed) error stop "descriptor acquisition failed"
  changed = reject_descriptor(descriptor)
  if (.not. changed) error stop "rejected descriptor was not closed"
  if (.not. descriptor_is_closed(descriptor)) error stop "descriptor remained open"
  changed = remove_descriptor(descriptor)
  if (changed) error stop "descriptor was closed more than once"
  if (descriptor_closes(descriptor) /= 1) error stop "incorrect close count"

  changed = acquire_descriptor(descriptor)
  if (.not. changed) error stop "descriptor reacquisition failed"
  changed = remove_descriptor(descriptor)
  if (.not. changed) error stop "removed descriptor was not closed"
  if (descriptor_closes(descriptor) /= 2) error stop "remove did not close exactly once"

  changed = enable_hotplug(backend_path, permission)
  if (changed) error stop "path backend received hotplug permission"
  if (hotplug_is_active(permission)) error stop "path hotplug permission became active"

  changed = enable_hotplug(backend_udev, permission)
  if (.not. changed) error stop "udev backend did not receive hotplug permission"
  changed = enable_hotplug(backend_udev, permission)
  if (changed) error stop "duplicate hotplug permission was issued"
  changed = disable_hotplug(permission)
  if (.not. changed) error stop "hotplug permission was not consumed"
  changed = disable_hotplug(permission)
  if (changed) error stop "hotplug permission was consumed twice"
end program verify_resource_lifecycle