smelling_salts/lib.rs
1// Copyright © 2020-2023 The Smelling Salts Contributors.
2//
3// Licensed under any of:
4// - Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
5// - Boost Software License, Version 1.0 (https://www.boost.org/LICENSE_1_0.txt)
6// - MIT License (https://mit-license.org/)
7// At your choosing (See accompanying files LICENSE_APACHE_2_0.txt,
8// LICENSE_MIT.txt and LICENSE_BOOST_1_0.txt).
9//
10//! Abstraction over OS APIs to handle asynchronous device waking.
11//!
12//! ## Getting Started
13//! Most devices are represented as file descriptors on unix-like operating
14//! systems (MacOS also has run loops). On Windows, devices are usually sockets
15//! or handles. WebAssembly running in the browser doesn't have a equivalent.
16//! To get around these device backend differences, Smelling Salts exposed an
17//! [`OsDevice`] type which has [`From`] conversions implemented for the
18//! platform types.
19//!
20//! An [`OsDevice`] by itself isn't that useful, though. When you have a handle
21//! to a device, you want to asynchronously watch it for events. For this, you
22//! construct a [`Device`], which implements [`Notify`](pasts::notify::Notify).
23//! But, general devices aren't that useful either, so you'll need to wrap it in
24//! your own custom type. Usually, you will filter out some of the events, so
25//! you'll need to implement [`Notify`](pasts::notify::Notify).
26//!
27//! Here's a simple example implementing a [`Notify`](pasts::notify::Notify) for
28//! stdin line reading:
29//!
30//! ```rust,no_run
31#![cfg_attr(target_os = "linux", doc = include_str!("../examples/stdin.rs"))]
32//! ```
33
34#![doc(
35 html_logo_url = "https://libcala.github.io/logo.svg",
36 html_favicon_url = "https://libcala.github.io/icon.svg",
37 html_root_url = "https://docs.rs/smelling_salts"
38)]
39#![warn(
40 anonymous_parameters,
41 missing_copy_implementations,
42 missing_debug_implementations,
43 missing_docs,
44 nonstandard_style,
45 rust_2018_idioms,
46 single_use_lifetimes,
47 trivial_casts,
48 trivial_numeric_casts,
49 unreachable_pub,
50 unused_extern_crates,
51 unused_qualifications,
52 variant_size_differences
53)]
54
55mod device;
56mod kind;
57mod watch;
58
59#[cfg_attr(target_os = "linux", path = "epoll.rs")]
60#[cfg_attr(not(target_os = "linux"), path = "mock.rs")]
61mod platform;
62
63pub use self::{device::Device, kind::OsDevice, watch::Watch};
64
65trait Interface {
66 const WATCH_INPUT: u32;
67 const WATCH_OUTPUT: u32;
68
69 /// Watch a [`DeviceKind`]
70 fn watch(kind: &kind::DeviceKind, watch: Watch) -> whisk::Channel;
71
72 /// Unwatch a [`DeviceKind`]
73 fn unwatch(kind: &kind::DeviceKind);
74}
75
76struct Platform;
77
78impl Platform {
79 fn watch(kind: &kind::DeviceKind, watch: Watch) -> whisk::Channel {
80 <Platform as Interface>::watch(kind, watch)
81 }
82
83 fn unwatch(kind: &kind::DeviceKind) {
84 <Platform as Interface>::unwatch(kind);
85 }
86}