pub trait BusDevice: Debug {
    type Timestamp: Sized;
    type NextDevice: BusDevice<Timestamp = Self::Timestamp>;

    fn next_device_mut(&mut self) -> &mut Self::NextDevice;
    fn next_device_ref(&self) -> &Self::NextDevice;
    fn into_next_device(self) -> Self::NextDevice;

    fn reset(&mut self, timestamp: Self::Timestamp) { ... }
    fn update_timestamp(&mut self, timestamp: Self::Timestamp) { ... }
    fn next_frame(&mut self, eof_timestamp: Self::Timestamp) { ... }
    fn read_io(
        &mut self,
        port: u16,
        timestamp: Self::Timestamp
    ) -> Option<(u8, Option<NonZeroU16>)> { ... } fn write_io(
        &mut self,
        port: u16,
        data: u8,
        timestamp: Self::Timestamp
    ) -> Option<u16> { ... } fn type_id(&self) -> TypeId
    where
        Self: 'static
, { ... } }
Expand description

An interface for emulating devices that communicate with the emulated CPU via I/O requests.

This trait allows attaching many, different devices to form a so-called “daisy chain”.

Implementations of this trait should be provided as an associated type of ControlUnit::BusDevice.

Required Associated Types§

A type used as a time-stamp.

A type of the next device in a daisy chain.

Required Methods§

Returns a mutable reference to the next device.

Returns a reference to the next device.

Destructs self and returns the instance of the next bus device.

Provided Methods§

Resets the device and all devices in this chain.

This method is called from ControlUnit::reset.

Default implementation forwards this call to the next device.

NOTE: Implementations should always forward this call down the chain after optionally applying it to self.

Examples found in repository?
src/bus/dynbus/serde.rs (line 279)
278
279
280
    fn reset(&mut self, timestamp: Self::Timestamp) {
        self.0.reset(timestamp)
    }
More examples
Hide additional examples
src/bus.rs (line 101)
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
    fn reset(&mut self, timestamp: Self::Timestamp) {
        self.next_device_mut().reset(timestamp)
    }
    /// This method should be called near the end of each frame.
    ///
    /// Default implementation forwards this call to the next device.
    ///
    /// **NOTE**: Implementations should always forward this call down the chain after optionally applying it
    /// to `self`.
    ///
    /// [ControlUnit::execute_next_frame]: crate::chip::ControlUnit::execute_next_frame
    #[inline(always)]
    fn update_timestamp(&mut self, timestamp: Self::Timestamp) {
        self.next_device_mut().update_timestamp(timestamp)
    }
    /// This method should be called just before the T-state counter of the control unit is wrapped when preparing
    /// for the next frame.
    ///
    /// It allows the devices that are tracking time to adjust stored timestamps accordingly by subtracting
    /// the total number of T-states per frame from the stored ones. The `eof_timestamp` argument indicates
    /// the total number of T-states in a single frame.
    ///
    /// Optionally enables implementations to perform an end-of-frame action.
    ///
    /// Default implementation forwards this call to the next device.
    ///
    /// **NOTE**: Implementations should always forward this call down the chain after optionally applying it
    /// to `self`.
    #[inline(always)]
    fn next_frame(&mut self, eof_timestamp: Self::Timestamp) {
        self.next_device_mut().next_frame(eof_timestamp)
    }
    /// This method is called by the control unit during an I/O read cycle.
    ///
    /// Default implementation forwards this call to the next device.
    ///
    /// Returns an optional tuple with the (data, insert wait states).
    ///
    /// **NOTE**: Implementations should only need to forward this call if it does not apply to this device
    /// or if not all bits are modified by the implementing device. In the latter case the result from the
    /// forwarded call should be logically `ANDed` with the result of reading from this device and if the
    /// upstream result is `None` the result should be returned with all unused bits set to 1.
    #[inline(always)]
    fn read_io(&mut self, port: u16, timestamp: Self::Timestamp) -> Option<(u8, Option<NonZeroU16>)> {
        self.next_device_mut().read_io(port, timestamp)
    }
    /// This method is called by the control unit during an I/O write cycle.
    ///
    /// Returns `Some(insert wait states)` if the device has blocked writing through it.
    ///
    /// Default implementation forwards this call to the next device.
    ///
    /// **NOTE**: Implementations should only forward this call to the next device if it does not apply
    /// to this device or if the device doesn't block writing. If the device blocks writing to downstream
    /// devices and the port matches, this method must return `true`. Otherwise this method should return
    /// the forwarded result.
    #[inline(always)]
    fn write_io(&mut self, port: u16, data: u8, timestamp: Self::Timestamp) -> Option<u16> {
        self.next_device_mut().write_io(port, data, timestamp)
    }
    /// Gets the `TypeId` of `self`.
    ///
    /// A required part for the ability to downcast dynamic `BusDevice` instances.
    ///
    /// # Safety
    /// The default implementation of this method must not be overwritten by the specializations.
    /// Consider this method as `final`.
    fn type_id(&self) -> TypeId where Self: 'static {
        TypeId::of::<Self>()
    }
}

impl<D: BusDevice> BusDevice for Box<D> {
    type Timestamp = D::Timestamp;
    type NextDevice = D::NextDevice;

    #[inline(always)]
    fn next_device_mut(&mut self) -> &mut Self::NextDevice {
        (**self).next_device_mut()
    }
    #[inline(always)]
    fn next_device_ref(&self) -> &Self::NextDevice {
        (**self).next_device_ref()
    }
    #[inline]
    fn into_next_device(self) -> Self::NextDevice {
        (*self).into_next_device()
    }
    #[inline]
    fn reset(&mut self, timestamp: Self::Timestamp) {
        (**self).reset(timestamp)
    }
    #[inline]
    fn update_timestamp(&mut self, timestamp: Self::Timestamp) {
        (**self).update_timestamp(timestamp)
    }
    #[inline]
    fn next_frame(&mut self, eof_timestamp: Self::Timestamp) {
        (**self).next_frame(eof_timestamp)
    }
    #[inline]
    fn read_io(&mut self, port: u16, timestamp: Self::Timestamp) -> Option<(u8, Option<NonZeroU16>)> {
        (**self).read_io(port, timestamp)
    }
    #[inline]
    fn write_io(&mut self, port: u16, data: u8, timestamp: Self::Timestamp) -> Option<u16> {
        (**self).write_io(port, data, timestamp)
    }
}

/// A helper trait for matching I/O port addresses.
pub trait PortAddress: Debug {
    /// Relevant address bits should be set to 1.
    const ADDRESS_MASK: u16;
    /// Bits from this constant will be matching only if `ADDRESS_MASK` constains 1 for bits in the same positions.
    const ADDRESS_BITS: u16;
    /// Returns `true` if a provided `address` masked with `ADDRESS_MASK` matches `ADDRESS_BITS`.
    #[inline]
    fn match_port(address: u16) -> bool {
        address & Self::ADDRESS_MASK == Self::ADDRESS_BITS & Self::ADDRESS_MASK
    }
}

/// A daisy-chain terminator device. Use it as the last device in a chain.
///
/// Substitute `T` with a timestamp type.
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "snapshot", derive(Serialize, Deserialize))]
pub struct NullDevice<T>(PhantomData<T>);

pub type VFNullDevice<V> = NullDevice<VFrameTs<V>>;

impl<T> Default for NullDevice<T> {
    #[inline(always)]
    fn default() -> Self {
        NullDevice(PhantomData)
    }
}

impl<T> BusDevice for NullDevice<T> {
    type Timestamp = T;
    type NextDevice = Self;

    #[inline(always)]
    fn next_device_mut(&mut self) -> &mut Self::NextDevice {
        self
    }
    #[inline(always)]
    fn next_device_ref(&self) -> &Self::NextDevice {
        self
    }
    #[inline(always)]
    fn into_next_device(self) -> Self::NextDevice {
        self
    }
    #[inline(always)]
    fn reset(&mut self, _timestamp: Self::Timestamp) {}

    #[inline(always)]
    fn update_timestamp(&mut self, _timestamp: Self::Timestamp) {}

    #[inline(always)]
    fn next_frame(&mut self, _timestamp: Self::Timestamp) {}

    #[inline(always)]
    fn read_io(&mut self, _port: u16, _timestamp: Self::Timestamp) -> Option<(u8, Option<NonZeroU16>)> {
        None
    }

    #[inline(always)]
    fn write_io(&mut self, _port: u16, _data: u8, _timestamp: Self::Timestamp) -> Option<u16> {
        None
    }
}

impl<T> fmt::Debug for NullDevice<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("NullDevice").finish()
    }
}

impl<T> fmt::Display for NullDevice<T> {
    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
        Ok(())
    }
}

/// A pseudo [BusDevice] allowing for plugging in and out a device at run time.
#[derive(Clone, Default, Debug)]
#[cfg_attr(feature = "snapshot", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "snapshot", serde(rename_all = "camelCase"))]
pub struct OptionalBusDevice<D, N> {
    /// The device that can be "plugged in".
    #[cfg_attr(feature = "snapshot", serde(default))]
    pub device: Option<D>,
    /// The next device in the daisy chain.
    #[cfg_attr(feature = "snapshot", serde(default))]
    pub next_device: N
}

impl<D, N> OptionalBusDevice<D, N>
    where D: BusDevice, N: BusDevice
{
    pub fn new(device: Option<D>, next_device: N) -> Self {
        OptionalBusDevice { device, next_device }
    }
}

impl<D, N> Deref for OptionalBusDevice<D, N> {
    type Target = Option<D>;
    fn deref(&self) -> &Self::Target {
        &self.device
    }
}

impl<D, N> DerefMut for OptionalBusDevice<D, N> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.device
    }
}

impl<D, N> BusDevice for OptionalBusDevice<D, N>
    where D: BusDevice,
          N: BusDevice<Timestamp=D::Timestamp>,
          D::Timestamp: Copy
{
    type Timestamp = D::Timestamp;
    type NextDevice = N;

    #[inline]
    fn next_device_mut(&mut self) -> &mut Self::NextDevice {
        &mut self.next_device
    }
    #[inline]
    fn next_device_ref(&self) -> &Self::NextDevice {
        &self.next_device
    }
    #[inline]
    fn into_next_device(self) -> Self::NextDevice {
        self.next_device
    }
    #[inline]
    fn reset(&mut self, timestamp: Self::Timestamp) {
        if let Some(device) = &mut self.device {
            device.reset(timestamp);
        }
        self.next_device.reset(timestamp);
    }
src/bus/dynbus.rs (line 282)
280
281
282
283
284
285
    fn reset(&mut self, timestamp: Self::Timestamp) {
        for dev in self.devices.iter_mut() {
            dev.reset(timestamp);
        }
        self.bus.reset(timestamp);
    }

This method should be called near the end of each frame.

Default implementation forwards this call to the next device.

NOTE: Implementations should always forward this call down the chain after optionally applying it to self.

Examples found in repository?
src/bus/dynbus/serde.rs (line 283)
282
283
284
    fn update_timestamp(&mut self, timestamp: Self::Timestamp) {
        self.0.update_timestamp(timestamp)
    }
More examples
Hide additional examples
src/bus.rs (line 113)
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
    fn update_timestamp(&mut self, timestamp: Self::Timestamp) {
        self.next_device_mut().update_timestamp(timestamp)
    }
    /// This method should be called just before the T-state counter of the control unit is wrapped when preparing
    /// for the next frame.
    ///
    /// It allows the devices that are tracking time to adjust stored timestamps accordingly by subtracting
    /// the total number of T-states per frame from the stored ones. The `eof_timestamp` argument indicates
    /// the total number of T-states in a single frame.
    ///
    /// Optionally enables implementations to perform an end-of-frame action.
    ///
    /// Default implementation forwards this call to the next device.
    ///
    /// **NOTE**: Implementations should always forward this call down the chain after optionally applying it
    /// to `self`.
    #[inline(always)]
    fn next_frame(&mut self, eof_timestamp: Self::Timestamp) {
        self.next_device_mut().next_frame(eof_timestamp)
    }
    /// This method is called by the control unit during an I/O read cycle.
    ///
    /// Default implementation forwards this call to the next device.
    ///
    /// Returns an optional tuple with the (data, insert wait states).
    ///
    /// **NOTE**: Implementations should only need to forward this call if it does not apply to this device
    /// or if not all bits are modified by the implementing device. In the latter case the result from the
    /// forwarded call should be logically `ANDed` with the result of reading from this device and if the
    /// upstream result is `None` the result should be returned with all unused bits set to 1.
    #[inline(always)]
    fn read_io(&mut self, port: u16, timestamp: Self::Timestamp) -> Option<(u8, Option<NonZeroU16>)> {
        self.next_device_mut().read_io(port, timestamp)
    }
    /// This method is called by the control unit during an I/O write cycle.
    ///
    /// Returns `Some(insert wait states)` if the device has blocked writing through it.
    ///
    /// Default implementation forwards this call to the next device.
    ///
    /// **NOTE**: Implementations should only forward this call to the next device if it does not apply
    /// to this device or if the device doesn't block writing. If the device blocks writing to downstream
    /// devices and the port matches, this method must return `true`. Otherwise this method should return
    /// the forwarded result.
    #[inline(always)]
    fn write_io(&mut self, port: u16, data: u8, timestamp: Self::Timestamp) -> Option<u16> {
        self.next_device_mut().write_io(port, data, timestamp)
    }
    /// Gets the `TypeId` of `self`.
    ///
    /// A required part for the ability to downcast dynamic `BusDevice` instances.
    ///
    /// # Safety
    /// The default implementation of this method must not be overwritten by the specializations.
    /// Consider this method as `final`.
    fn type_id(&self) -> TypeId where Self: 'static {
        TypeId::of::<Self>()
    }
}

impl<D: BusDevice> BusDevice for Box<D> {
    type Timestamp = D::Timestamp;
    type NextDevice = D::NextDevice;

    #[inline(always)]
    fn next_device_mut(&mut self) -> &mut Self::NextDevice {
        (**self).next_device_mut()
    }
    #[inline(always)]
    fn next_device_ref(&self) -> &Self::NextDevice {
        (**self).next_device_ref()
    }
    #[inline]
    fn into_next_device(self) -> Self::NextDevice {
        (*self).into_next_device()
    }
    #[inline]
    fn reset(&mut self, timestamp: Self::Timestamp) {
        (**self).reset(timestamp)
    }
    #[inline]
    fn update_timestamp(&mut self, timestamp: Self::Timestamp) {
        (**self).update_timestamp(timestamp)
    }
    #[inline]
    fn next_frame(&mut self, eof_timestamp: Self::Timestamp) {
        (**self).next_frame(eof_timestamp)
    }
    #[inline]
    fn read_io(&mut self, port: u16, timestamp: Self::Timestamp) -> Option<(u8, Option<NonZeroU16>)> {
        (**self).read_io(port, timestamp)
    }
    #[inline]
    fn write_io(&mut self, port: u16, data: u8, timestamp: Self::Timestamp) -> Option<u16> {
        (**self).write_io(port, data, timestamp)
    }
}

/// A helper trait for matching I/O port addresses.
pub trait PortAddress: Debug {
    /// Relevant address bits should be set to 1.
    const ADDRESS_MASK: u16;
    /// Bits from this constant will be matching only if `ADDRESS_MASK` constains 1 for bits in the same positions.
    const ADDRESS_BITS: u16;
    /// Returns `true` if a provided `address` masked with `ADDRESS_MASK` matches `ADDRESS_BITS`.
    #[inline]
    fn match_port(address: u16) -> bool {
        address & Self::ADDRESS_MASK == Self::ADDRESS_BITS & Self::ADDRESS_MASK
    }
}

/// A daisy-chain terminator device. Use it as the last device in a chain.
///
/// Substitute `T` with a timestamp type.
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "snapshot", derive(Serialize, Deserialize))]
pub struct NullDevice<T>(PhantomData<T>);

pub type VFNullDevice<V> = NullDevice<VFrameTs<V>>;

impl<T> Default for NullDevice<T> {
    #[inline(always)]
    fn default() -> Self {
        NullDevice(PhantomData)
    }
}

impl<T> BusDevice for NullDevice<T> {
    type Timestamp = T;
    type NextDevice = Self;

    #[inline(always)]
    fn next_device_mut(&mut self) -> &mut Self::NextDevice {
        self
    }
    #[inline(always)]
    fn next_device_ref(&self) -> &Self::NextDevice {
        self
    }
    #[inline(always)]
    fn into_next_device(self) -> Self::NextDevice {
        self
    }
    #[inline(always)]
    fn reset(&mut self, _timestamp: Self::Timestamp) {}

    #[inline(always)]
    fn update_timestamp(&mut self, _timestamp: Self::Timestamp) {}

    #[inline(always)]
    fn next_frame(&mut self, _timestamp: Self::Timestamp) {}

    #[inline(always)]
    fn read_io(&mut self, _port: u16, _timestamp: Self::Timestamp) -> Option<(u8, Option<NonZeroU16>)> {
        None
    }

    #[inline(always)]
    fn write_io(&mut self, _port: u16, _data: u8, _timestamp: Self::Timestamp) -> Option<u16> {
        None
    }
}

impl<T> fmt::Debug for NullDevice<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("NullDevice").finish()
    }
}

impl<T> fmt::Display for NullDevice<T> {
    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
        Ok(())
    }
}

/// A pseudo [BusDevice] allowing for plugging in and out a device at run time.
#[derive(Clone, Default, Debug)]
#[cfg_attr(feature = "snapshot", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "snapshot", serde(rename_all = "camelCase"))]
pub struct OptionalBusDevice<D, N> {
    /// The device that can be "plugged in".
    #[cfg_attr(feature = "snapshot", serde(default))]
    pub device: Option<D>,
    /// The next device in the daisy chain.
    #[cfg_attr(feature = "snapshot", serde(default))]
    pub next_device: N
}

impl<D, N> OptionalBusDevice<D, N>
    where D: BusDevice, N: BusDevice
{
    pub fn new(device: Option<D>, next_device: N) -> Self {
        OptionalBusDevice { device, next_device }
    }
}

impl<D, N> Deref for OptionalBusDevice<D, N> {
    type Target = Option<D>;
    fn deref(&self) -> &Self::Target {
        &self.device
    }
}

impl<D, N> DerefMut for OptionalBusDevice<D, N> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.device
    }
}

impl<D, N> BusDevice for OptionalBusDevice<D, N>
    where D: BusDevice,
          N: BusDevice<Timestamp=D::Timestamp>,
          D::Timestamp: Copy
{
    type Timestamp = D::Timestamp;
    type NextDevice = N;

    #[inline]
    fn next_device_mut(&mut self) -> &mut Self::NextDevice {
        &mut self.next_device
    }
    #[inline]
    fn next_device_ref(&self) -> &Self::NextDevice {
        &self.next_device
    }
    #[inline]
    fn into_next_device(self) -> Self::NextDevice {
        self.next_device
    }
    #[inline]
    fn reset(&mut self, timestamp: Self::Timestamp) {
        if let Some(device) = &mut self.device {
            device.reset(timestamp);
        }
        self.next_device.reset(timestamp);
    }
    #[inline]
    fn update_timestamp(&mut self, timestamp: Self::Timestamp) {
        if let Some(device) = &mut self.device {
            device.update_timestamp(timestamp);
        }
        self.next_device.update_timestamp(timestamp);
    }
src/bus/dynbus.rs (line 290)
288
289
290
291
292
293
    fn update_timestamp(&mut self, timestamp: Self::Timestamp) {
        for dev in self.devices.iter_mut() {
            dev.update_timestamp(timestamp);
        }
        self.bus.update_timestamp(timestamp);
    }

This method should be called just before the T-state counter of the control unit is wrapped when preparing for the next frame.

It allows the devices that are tracking time to adjust stored timestamps accordingly by subtracting the total number of T-states per frame from the stored ones. The eof_timestamp argument indicates the total number of T-states in a single frame.

Optionally enables implementations to perform an end-of-frame action.

Default implementation forwards this call to the next device.

NOTE: Implementations should always forward this call down the chain after optionally applying it to self.

Examples found in repository?
src/bus/dynbus/serde.rs (line 287)
286
287
288
    fn next_frame(&mut self, timestamp: Self::Timestamp) {
        self.0.next_frame(timestamp)
    }
More examples
Hide additional examples
src/bus.rs (line 130)
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
    fn next_frame(&mut self, eof_timestamp: Self::Timestamp) {
        self.next_device_mut().next_frame(eof_timestamp)
    }
    /// This method is called by the control unit during an I/O read cycle.
    ///
    /// Default implementation forwards this call to the next device.
    ///
    /// Returns an optional tuple with the (data, insert wait states).
    ///
    /// **NOTE**: Implementations should only need to forward this call if it does not apply to this device
    /// or if not all bits are modified by the implementing device. In the latter case the result from the
    /// forwarded call should be logically `ANDed` with the result of reading from this device and if the
    /// upstream result is `None` the result should be returned with all unused bits set to 1.
    #[inline(always)]
    fn read_io(&mut self, port: u16, timestamp: Self::Timestamp) -> Option<(u8, Option<NonZeroU16>)> {
        self.next_device_mut().read_io(port, timestamp)
    }
    /// This method is called by the control unit during an I/O write cycle.
    ///
    /// Returns `Some(insert wait states)` if the device has blocked writing through it.
    ///
    /// Default implementation forwards this call to the next device.
    ///
    /// **NOTE**: Implementations should only forward this call to the next device if it does not apply
    /// to this device or if the device doesn't block writing. If the device blocks writing to downstream
    /// devices and the port matches, this method must return `true`. Otherwise this method should return
    /// the forwarded result.
    #[inline(always)]
    fn write_io(&mut self, port: u16, data: u8, timestamp: Self::Timestamp) -> Option<u16> {
        self.next_device_mut().write_io(port, data, timestamp)
    }
    /// Gets the `TypeId` of `self`.
    ///
    /// A required part for the ability to downcast dynamic `BusDevice` instances.
    ///
    /// # Safety
    /// The default implementation of this method must not be overwritten by the specializations.
    /// Consider this method as `final`.
    fn type_id(&self) -> TypeId where Self: 'static {
        TypeId::of::<Self>()
    }
}

impl<D: BusDevice> BusDevice for Box<D> {
    type Timestamp = D::Timestamp;
    type NextDevice = D::NextDevice;

    #[inline(always)]
    fn next_device_mut(&mut self) -> &mut Self::NextDevice {
        (**self).next_device_mut()
    }
    #[inline(always)]
    fn next_device_ref(&self) -> &Self::NextDevice {
        (**self).next_device_ref()
    }
    #[inline]
    fn into_next_device(self) -> Self::NextDevice {
        (*self).into_next_device()
    }
    #[inline]
    fn reset(&mut self, timestamp: Self::Timestamp) {
        (**self).reset(timestamp)
    }
    #[inline]
    fn update_timestamp(&mut self, timestamp: Self::Timestamp) {
        (**self).update_timestamp(timestamp)
    }
    #[inline]
    fn next_frame(&mut self, eof_timestamp: Self::Timestamp) {
        (**self).next_frame(eof_timestamp)
    }
    #[inline]
    fn read_io(&mut self, port: u16, timestamp: Self::Timestamp) -> Option<(u8, Option<NonZeroU16>)> {
        (**self).read_io(port, timestamp)
    }
    #[inline]
    fn write_io(&mut self, port: u16, data: u8, timestamp: Self::Timestamp) -> Option<u16> {
        (**self).write_io(port, data, timestamp)
    }
}

/// A helper trait for matching I/O port addresses.
pub trait PortAddress: Debug {
    /// Relevant address bits should be set to 1.
    const ADDRESS_MASK: u16;
    /// Bits from this constant will be matching only if `ADDRESS_MASK` constains 1 for bits in the same positions.
    const ADDRESS_BITS: u16;
    /// Returns `true` if a provided `address` masked with `ADDRESS_MASK` matches `ADDRESS_BITS`.
    #[inline]
    fn match_port(address: u16) -> bool {
        address & Self::ADDRESS_MASK == Self::ADDRESS_BITS & Self::ADDRESS_MASK
    }
}

/// A daisy-chain terminator device. Use it as the last device in a chain.
///
/// Substitute `T` with a timestamp type.
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "snapshot", derive(Serialize, Deserialize))]
pub struct NullDevice<T>(PhantomData<T>);

pub type VFNullDevice<V> = NullDevice<VFrameTs<V>>;

impl<T> Default for NullDevice<T> {
    #[inline(always)]
    fn default() -> Self {
        NullDevice(PhantomData)
    }
}

impl<T> BusDevice for NullDevice<T> {
    type Timestamp = T;
    type NextDevice = Self;

    #[inline(always)]
    fn next_device_mut(&mut self) -> &mut Self::NextDevice {
        self
    }
    #[inline(always)]
    fn next_device_ref(&self) -> &Self::NextDevice {
        self
    }
    #[inline(always)]
    fn into_next_device(self) -> Self::NextDevice {
        self
    }
    #[inline(always)]
    fn reset(&mut self, _timestamp: Self::Timestamp) {}

    #[inline(always)]
    fn update_timestamp(&mut self, _timestamp: Self::Timestamp) {}

    #[inline(always)]
    fn next_frame(&mut self, _timestamp: Self::Timestamp) {}

    #[inline(always)]
    fn read_io(&mut self, _port: u16, _timestamp: Self::Timestamp) -> Option<(u8, Option<NonZeroU16>)> {
        None
    }

    #[inline(always)]
    fn write_io(&mut self, _port: u16, _data: u8, _timestamp: Self::Timestamp) -> Option<u16> {
        None
    }
}

impl<T> fmt::Debug for NullDevice<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("NullDevice").finish()
    }
}

impl<T> fmt::Display for NullDevice<T> {
    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
        Ok(())
    }
}

/// A pseudo [BusDevice] allowing for plugging in and out a device at run time.
#[derive(Clone, Default, Debug)]
#[cfg_attr(feature = "snapshot", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "snapshot", serde(rename_all = "camelCase"))]
pub struct OptionalBusDevice<D, N> {
    /// The device that can be "plugged in".
    #[cfg_attr(feature = "snapshot", serde(default))]
    pub device: Option<D>,
    /// The next device in the daisy chain.
    #[cfg_attr(feature = "snapshot", serde(default))]
    pub next_device: N
}

impl<D, N> OptionalBusDevice<D, N>
    where D: BusDevice, N: BusDevice
{
    pub fn new(device: Option<D>, next_device: N) -> Self {
        OptionalBusDevice { device, next_device }
    }
}

impl<D, N> Deref for OptionalBusDevice<D, N> {
    type Target = Option<D>;
    fn deref(&self) -> &Self::Target {
        &self.device
    }
}

impl<D, N> DerefMut for OptionalBusDevice<D, N> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.device
    }
}

impl<D, N> BusDevice for OptionalBusDevice<D, N>
    where D: BusDevice,
          N: BusDevice<Timestamp=D::Timestamp>,
          D::Timestamp: Copy
{
    type Timestamp = D::Timestamp;
    type NextDevice = N;

    #[inline]
    fn next_device_mut(&mut self) -> &mut Self::NextDevice {
        &mut self.next_device
    }
    #[inline]
    fn next_device_ref(&self) -> &Self::NextDevice {
        &self.next_device
    }
    #[inline]
    fn into_next_device(self) -> Self::NextDevice {
        self.next_device
    }
    #[inline]
    fn reset(&mut self, timestamp: Self::Timestamp) {
        if let Some(device) = &mut self.device {
            device.reset(timestamp);
        }
        self.next_device.reset(timestamp);
    }
    #[inline]
    fn update_timestamp(&mut self, timestamp: Self::Timestamp) {
        if let Some(device) = &mut self.device {
            device.update_timestamp(timestamp);
        }
        self.next_device.update_timestamp(timestamp);
    }
    #[inline]
    fn next_frame(&mut self, timestamp: Self::Timestamp) {
        if let Some(device) = &mut self.device {
            device.next_frame(timestamp);
        }
        self.next_device.next_frame(timestamp);
    }
src/bus/dynbus.rs (line 298)
296
297
298
299
300
301
    fn next_frame(&mut self, timestamp: Self::Timestamp) {
        for dev in self.devices.iter_mut() {
            dev.next_frame(timestamp);
        }
        self.bus.next_frame(timestamp);
    }

This method is called by the control unit during an I/O read cycle.

Default implementation forwards this call to the next device.

Returns an optional tuple with the (data, insert wait states).

NOTE: Implementations should only need to forward this call if it does not apply to this device or if not all bits are modified by the implementing device. In the latter case the result from the forwarded call should be logically ANDed with the result of reading from this device and if the upstream result is None the result should be returned with all unused bits set to 1.

Examples found in repository?
src/bus/dynbus/serde.rs (line 291)
290
291
292
    fn read_io(&mut self, port: u16, timestamp: Self::Timestamp) -> Option<(u8, Option<NonZeroU16>)> {
        self.0.read_io(port, timestamp)
    }
More examples
Hide additional examples
src/bus.rs (line 144)
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
    fn read_io(&mut self, port: u16, timestamp: Self::Timestamp) -> Option<(u8, Option<NonZeroU16>)> {
        self.next_device_mut().read_io(port, timestamp)
    }
    /// This method is called by the control unit during an I/O write cycle.
    ///
    /// Returns `Some(insert wait states)` if the device has blocked writing through it.
    ///
    /// Default implementation forwards this call to the next device.
    ///
    /// **NOTE**: Implementations should only forward this call to the next device if it does not apply
    /// to this device or if the device doesn't block writing. If the device blocks writing to downstream
    /// devices and the port matches, this method must return `true`. Otherwise this method should return
    /// the forwarded result.
    #[inline(always)]
    fn write_io(&mut self, port: u16, data: u8, timestamp: Self::Timestamp) -> Option<u16> {
        self.next_device_mut().write_io(port, data, timestamp)
    }
    /// Gets the `TypeId` of `self`.
    ///
    /// A required part for the ability to downcast dynamic `BusDevice` instances.
    ///
    /// # Safety
    /// The default implementation of this method must not be overwritten by the specializations.
    /// Consider this method as `final`.
    fn type_id(&self) -> TypeId where Self: 'static {
        TypeId::of::<Self>()
    }
}

impl<D: BusDevice> BusDevice for Box<D> {
    type Timestamp = D::Timestamp;
    type NextDevice = D::NextDevice;

    #[inline(always)]
    fn next_device_mut(&mut self) -> &mut Self::NextDevice {
        (**self).next_device_mut()
    }
    #[inline(always)]
    fn next_device_ref(&self) -> &Self::NextDevice {
        (**self).next_device_ref()
    }
    #[inline]
    fn into_next_device(self) -> Self::NextDevice {
        (*self).into_next_device()
    }
    #[inline]
    fn reset(&mut self, timestamp: Self::Timestamp) {
        (**self).reset(timestamp)
    }
    #[inline]
    fn update_timestamp(&mut self, timestamp: Self::Timestamp) {
        (**self).update_timestamp(timestamp)
    }
    #[inline]
    fn next_frame(&mut self, eof_timestamp: Self::Timestamp) {
        (**self).next_frame(eof_timestamp)
    }
    #[inline]
    fn read_io(&mut self, port: u16, timestamp: Self::Timestamp) -> Option<(u8, Option<NonZeroU16>)> {
        (**self).read_io(port, timestamp)
    }
    #[inline]
    fn write_io(&mut self, port: u16, data: u8, timestamp: Self::Timestamp) -> Option<u16> {
        (**self).write_io(port, data, timestamp)
    }
}

/// A helper trait for matching I/O port addresses.
pub trait PortAddress: Debug {
    /// Relevant address bits should be set to 1.
    const ADDRESS_MASK: u16;
    /// Bits from this constant will be matching only if `ADDRESS_MASK` constains 1 for bits in the same positions.
    const ADDRESS_BITS: u16;
    /// Returns `true` if a provided `address` masked with `ADDRESS_MASK` matches `ADDRESS_BITS`.
    #[inline]
    fn match_port(address: u16) -> bool {
        address & Self::ADDRESS_MASK == Self::ADDRESS_BITS & Self::ADDRESS_MASK
    }
}

/// A daisy-chain terminator device. Use it as the last device in a chain.
///
/// Substitute `T` with a timestamp type.
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "snapshot", derive(Serialize, Deserialize))]
pub struct NullDevice<T>(PhantomData<T>);

pub type VFNullDevice<V> = NullDevice<VFrameTs<V>>;

impl<T> Default for NullDevice<T> {
    #[inline(always)]
    fn default() -> Self {
        NullDevice(PhantomData)
    }
}

impl<T> BusDevice for NullDevice<T> {
    type Timestamp = T;
    type NextDevice = Self;

    #[inline(always)]
    fn next_device_mut(&mut self) -> &mut Self::NextDevice {
        self
    }
    #[inline(always)]
    fn next_device_ref(&self) -> &Self::NextDevice {
        self
    }
    #[inline(always)]
    fn into_next_device(self) -> Self::NextDevice {
        self
    }
    #[inline(always)]
    fn reset(&mut self, _timestamp: Self::Timestamp) {}

    #[inline(always)]
    fn update_timestamp(&mut self, _timestamp: Self::Timestamp) {}

    #[inline(always)]
    fn next_frame(&mut self, _timestamp: Self::Timestamp) {}

    #[inline(always)]
    fn read_io(&mut self, _port: u16, _timestamp: Self::Timestamp) -> Option<(u8, Option<NonZeroU16>)> {
        None
    }

    #[inline(always)]
    fn write_io(&mut self, _port: u16, _data: u8, _timestamp: Self::Timestamp) -> Option<u16> {
        None
    }
}

impl<T> fmt::Debug for NullDevice<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("NullDevice").finish()
    }
}

impl<T> fmt::Display for NullDevice<T> {
    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
        Ok(())
    }
}

/// A pseudo [BusDevice] allowing for plugging in and out a device at run time.
#[derive(Clone, Default, Debug)]
#[cfg_attr(feature = "snapshot", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "snapshot", serde(rename_all = "camelCase"))]
pub struct OptionalBusDevice<D, N> {
    /// The device that can be "plugged in".
    #[cfg_attr(feature = "snapshot", serde(default))]
    pub device: Option<D>,
    /// The next device in the daisy chain.
    #[cfg_attr(feature = "snapshot", serde(default))]
    pub next_device: N
}

impl<D, N> OptionalBusDevice<D, N>
    where D: BusDevice, N: BusDevice
{
    pub fn new(device: Option<D>, next_device: N) -> Self {
        OptionalBusDevice { device, next_device }
    }
}

impl<D, N> Deref for OptionalBusDevice<D, N> {
    type Target = Option<D>;
    fn deref(&self) -> &Self::Target {
        &self.device
    }
}

impl<D, N> DerefMut for OptionalBusDevice<D, N> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.device
    }
}

impl<D, N> BusDevice for OptionalBusDevice<D, N>
    where D: BusDevice,
          N: BusDevice<Timestamp=D::Timestamp>,
          D::Timestamp: Copy
{
    type Timestamp = D::Timestamp;
    type NextDevice = N;

    #[inline]
    fn next_device_mut(&mut self) -> &mut Self::NextDevice {
        &mut self.next_device
    }
    #[inline]
    fn next_device_ref(&self) -> &Self::NextDevice {
        &self.next_device
    }
    #[inline]
    fn into_next_device(self) -> Self::NextDevice {
        self.next_device
    }
    #[inline]
    fn reset(&mut self, timestamp: Self::Timestamp) {
        if let Some(device) = &mut self.device {
            device.reset(timestamp);
        }
        self.next_device.reset(timestamp);
    }
    #[inline]
    fn update_timestamp(&mut self, timestamp: Self::Timestamp) {
        if let Some(device) = &mut self.device {
            device.update_timestamp(timestamp);
        }
        self.next_device.update_timestamp(timestamp);
    }
    #[inline]
    fn next_frame(&mut self, timestamp: Self::Timestamp) {
        if let Some(device) = &mut self.device {
            device.next_frame(timestamp);
        }
        self.next_device.next_frame(timestamp);
    }
    #[inline]
    fn read_io(&mut self, port: u16, timestamp: Self::Timestamp) -> Option<(u8, Option<NonZeroU16>)> {
        let dev_data = if let Some((data, ws)) = self.device
                            .as_mut()
                            .and_then(|dev| dev.read_io(port, timestamp)) {
            if ws.is_some() {
            // we assume a halting device takes highest priority in this request
                return Some((data, ws))
            }
            Some(data)
        }
        else {
            None
        };
        if let Some((bus_data, ws)) = self.next_device.read_io(port, timestamp) {
            let data = bus_data & dev_data.unwrap_or(!0);
            return Some((data, ws))
        }
        dev_data.map(|data| (data, None))
    }
src/bus/dynbus.rs (line 307)
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
    fn read_io(&mut self, port: u16, timestamp: Self::Timestamp) -> Option<(u8, Option<NonZeroU16>)> {
        let mut bus_data = None;
        for dev in self.devices.iter_mut() {
            if let Some((data, ws)) = dev.read_io(port, timestamp) {
                let data = data & bus_data.unwrap_or(!0);
                if ws.is_some() {
                    return Some((data, ws));
                }
                bus_data = Some(data);
            }
        }
        if let Some((data, ws)) = self.bus.read_io(port, timestamp) {
            return Some((data & bus_data.unwrap_or(!0), ws))
        }
        bus_data.map(|data| (data, None))
    }

This method is called by the control unit during an I/O write cycle.

Returns Some(insert wait states) if the device has blocked writing through it.

Default implementation forwards this call to the next device.

NOTE: Implementations should only forward this call to the next device if it does not apply to this device or if the device doesn’t block writing. If the device blocks writing to downstream devices and the port matches, this method must return true. Otherwise this method should return the forwarded result.

Examples found in repository?
src/bus/dynbus/serde.rs (line 295)
294
295
296
    fn write_io(&mut self, port: u16, data: u8, timestamp: Self::Timestamp) -> Option<u16> {
        self.0.write_io(port, data, timestamp)
    }
More examples
Hide additional examples
src/bus.rs (line 158)
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
    fn write_io(&mut self, port: u16, data: u8, timestamp: Self::Timestamp) -> Option<u16> {
        self.next_device_mut().write_io(port, data, timestamp)
    }
    /// Gets the `TypeId` of `self`.
    ///
    /// A required part for the ability to downcast dynamic `BusDevice` instances.
    ///
    /// # Safety
    /// The default implementation of this method must not be overwritten by the specializations.
    /// Consider this method as `final`.
    fn type_id(&self) -> TypeId where Self: 'static {
        TypeId::of::<Self>()
    }
}

impl<D: BusDevice> BusDevice for Box<D> {
    type Timestamp = D::Timestamp;
    type NextDevice = D::NextDevice;

    #[inline(always)]
    fn next_device_mut(&mut self) -> &mut Self::NextDevice {
        (**self).next_device_mut()
    }
    #[inline(always)]
    fn next_device_ref(&self) -> &Self::NextDevice {
        (**self).next_device_ref()
    }
    #[inline]
    fn into_next_device(self) -> Self::NextDevice {
        (*self).into_next_device()
    }
    #[inline]
    fn reset(&mut self, timestamp: Self::Timestamp) {
        (**self).reset(timestamp)
    }
    #[inline]
    fn update_timestamp(&mut self, timestamp: Self::Timestamp) {
        (**self).update_timestamp(timestamp)
    }
    #[inline]
    fn next_frame(&mut self, eof_timestamp: Self::Timestamp) {
        (**self).next_frame(eof_timestamp)
    }
    #[inline]
    fn read_io(&mut self, port: u16, timestamp: Self::Timestamp) -> Option<(u8, Option<NonZeroU16>)> {
        (**self).read_io(port, timestamp)
    }
    #[inline]
    fn write_io(&mut self, port: u16, data: u8, timestamp: Self::Timestamp) -> Option<u16> {
        (**self).write_io(port, data, timestamp)
    }
}

/// A helper trait for matching I/O port addresses.
pub trait PortAddress: Debug {
    /// Relevant address bits should be set to 1.
    const ADDRESS_MASK: u16;
    /// Bits from this constant will be matching only if `ADDRESS_MASK` constains 1 for bits in the same positions.
    const ADDRESS_BITS: u16;
    /// Returns `true` if a provided `address` masked with `ADDRESS_MASK` matches `ADDRESS_BITS`.
    #[inline]
    fn match_port(address: u16) -> bool {
        address & Self::ADDRESS_MASK == Self::ADDRESS_BITS & Self::ADDRESS_MASK
    }
}

/// A daisy-chain terminator device. Use it as the last device in a chain.
///
/// Substitute `T` with a timestamp type.
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "snapshot", derive(Serialize, Deserialize))]
pub struct NullDevice<T>(PhantomData<T>);

pub type VFNullDevice<V> = NullDevice<VFrameTs<V>>;

impl<T> Default for NullDevice<T> {
    #[inline(always)]
    fn default() -> Self {
        NullDevice(PhantomData)
    }
}

impl<T> BusDevice for NullDevice<T> {
    type Timestamp = T;
    type NextDevice = Self;

    #[inline(always)]
    fn next_device_mut(&mut self) -> &mut Self::NextDevice {
        self
    }
    #[inline(always)]
    fn next_device_ref(&self) -> &Self::NextDevice {
        self
    }
    #[inline(always)]
    fn into_next_device(self) -> Self::NextDevice {
        self
    }
    #[inline(always)]
    fn reset(&mut self, _timestamp: Self::Timestamp) {}

    #[inline(always)]
    fn update_timestamp(&mut self, _timestamp: Self::Timestamp) {}

    #[inline(always)]
    fn next_frame(&mut self, _timestamp: Self::Timestamp) {}

    #[inline(always)]
    fn read_io(&mut self, _port: u16, _timestamp: Self::Timestamp) -> Option<(u8, Option<NonZeroU16>)> {
        None
    }

    #[inline(always)]
    fn write_io(&mut self, _port: u16, _data: u8, _timestamp: Self::Timestamp) -> Option<u16> {
        None
    }
}

impl<T> fmt::Debug for NullDevice<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("NullDevice").finish()
    }
}

impl<T> fmt::Display for NullDevice<T> {
    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
        Ok(())
    }
}

/// A pseudo [BusDevice] allowing for plugging in and out a device at run time.
#[derive(Clone, Default, Debug)]
#[cfg_attr(feature = "snapshot", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "snapshot", serde(rename_all = "camelCase"))]
pub struct OptionalBusDevice<D, N> {
    /// The device that can be "plugged in".
    #[cfg_attr(feature = "snapshot", serde(default))]
    pub device: Option<D>,
    /// The next device in the daisy chain.
    #[cfg_attr(feature = "snapshot", serde(default))]
    pub next_device: N
}

impl<D, N> OptionalBusDevice<D, N>
    where D: BusDevice, N: BusDevice
{
    pub fn new(device: Option<D>, next_device: N) -> Self {
        OptionalBusDevice { device, next_device }
    }
}

impl<D, N> Deref for OptionalBusDevice<D, N> {
    type Target = Option<D>;
    fn deref(&self) -> &Self::Target {
        &self.device
    }
}

impl<D, N> DerefMut for OptionalBusDevice<D, N> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.device
    }
}

impl<D, N> BusDevice for OptionalBusDevice<D, N>
    where D: BusDevice,
          N: BusDevice<Timestamp=D::Timestamp>,
          D::Timestamp: Copy
{
    type Timestamp = D::Timestamp;
    type NextDevice = N;

    #[inline]
    fn next_device_mut(&mut self) -> &mut Self::NextDevice {
        &mut self.next_device
    }
    #[inline]
    fn next_device_ref(&self) -> &Self::NextDevice {
        &self.next_device
    }
    #[inline]
    fn into_next_device(self) -> Self::NextDevice {
        self.next_device
    }
    #[inline]
    fn reset(&mut self, timestamp: Self::Timestamp) {
        if let Some(device) = &mut self.device {
            device.reset(timestamp);
        }
        self.next_device.reset(timestamp);
    }
    #[inline]
    fn update_timestamp(&mut self, timestamp: Self::Timestamp) {
        if let Some(device) = &mut self.device {
            device.update_timestamp(timestamp);
        }
        self.next_device.update_timestamp(timestamp);
    }
    #[inline]
    fn next_frame(&mut self, timestamp: Self::Timestamp) {
        if let Some(device) = &mut self.device {
            device.next_frame(timestamp);
        }
        self.next_device.next_frame(timestamp);
    }
    #[inline]
    fn read_io(&mut self, port: u16, timestamp: Self::Timestamp) -> Option<(u8, Option<NonZeroU16>)> {
        let dev_data = if let Some((data, ws)) = self.device
                            .as_mut()
                            .and_then(|dev| dev.read_io(port, timestamp)) {
            if ws.is_some() {
            // we assume a halting device takes highest priority in this request
                return Some((data, ws))
            }
            Some(data)
        }
        else {
            None
        };
        if let Some((bus_data, ws)) = self.next_device.read_io(port, timestamp) {
            let data = bus_data & dev_data.unwrap_or(!0);
            return Some((data, ws))
        }
        dev_data.map(|data| (data, None))
    }

    #[inline]
    fn write_io(&mut self, port: u16, data: u8, timestamp: Self::Timestamp) -> Option<u16> {
        if let Some(device) = &mut self.device {
            if let Some(ws) = device.write_io(port, data, timestamp) {
                return Some(ws)
            }
        }
        self.next_device.write_io(port, data, timestamp)
    }
src/bus/dynbus.rs (line 324)
322
323
324
325
326
327
328
329
    fn write_io(&mut self, port: u16, data: u8, timestamp: Self::Timestamp) -> Option<u16> {
        for dev in self.devices.iter_mut() {
            if let Some(res) = dev.write_io(port, data, timestamp) {
                return Some(res);
            }
        }
        self.bus.write_io(port, data, timestamp)
    }

Gets the TypeId of self.

A required part for the ability to downcast dynamic BusDevice instances.

Safety

The default implementation of this method must not be overwritten by the specializations. Consider this method as final.

Examples found in repository?
src/bus.rs (line 45)
44
45
46
    pub fn is<D: NamedBusDevice<T> + 'static>(&self) -> bool {
        TypeId::of::<D>() == self.type_id()
    }

Implementations on Foreign Types§

Implementors§