#[repr(C)]
pub struct Api {
Show 49 fields pub api_version_get: extern "C" fn() -> Version, pub bios_version_get: extern "C" fn() -> FfiString<'static>, pub serial_get_info: extern "C" fn(device_id: u8) -> FfiOption<DeviceInfo>, pub serial_configure: extern "C" fn(device_id: u8, config: Config) -> ApiResult<()>, pub serial_write: extern "C" fn(device_id: u8, data: FfiByteSlice<'_>, timeout: FfiOption<Timeout>) -> ApiResult<usize>, pub serial_read: extern "C" fn(device_id: u8, data: FfiBuffer<'_>, timeout: FfiOption<Timeout>) -> ApiResult<usize>, pub time_clock_get: extern "C" fn() -> Time, pub time_clock_set: extern "C" fn(time: Time), pub time_ticks_get: extern "C" fn() -> Ticks, pub time_ticks_per_second: extern "C" fn() -> Ticks, pub configuration_get: extern "C" fn(buffer: FfiBuffer<'_>) -> ApiResult<usize>, pub configuration_set: extern "C" fn(buffer: FfiByteSlice<'_>) -> ApiResult<()>, pub video_is_valid_mode: extern "C" fn(mode: Mode) -> bool, pub video_mode_needs_vram: extern "C" fn(mode: Mode) -> bool, pub video_set_mode: unsafe extern "C" fn(mode: Mode, vram: *mut u32) -> ApiResult<()>, pub video_get_mode: extern "C" fn() -> Mode, pub video_get_framebuffer: extern "C" fn() -> *mut u32, pub video_wait_for_line: extern "C" fn(line: u16), pub video_get_palette: extern "C" fn(palette_idx: u8) -> FfiOption<RGBColour>, pub video_set_palette: extern "C" fn(palette_idx: u8, _: RGBColour), pub video_set_whole_palette: unsafe extern "C" fn(start: *const RGBColour, length: usize), pub memory_get_region: extern "C" fn(region_index: u8) -> FfiOption<MemoryRegion>, pub hid_get_event: extern "C" fn() -> ApiResult<FfiOption<HidEvent>>, pub hid_set_leds: extern "C" fn(leds: KeyboardLeds) -> ApiResult<()>, pub i2c_bus_get_info: extern "C" fn(bus_id: u8) -> FfiOption<BusInfo>, pub i2c_write_read: extern "C" fn(bus_id: u8, i2c_device_address: u8, tx: FfiByteSlice<'_>, tx2: FfiByteSlice<'_>, rx: FfiBuffer<'_>) -> ApiResult<()>, pub audio_mixer_channel_get_info: extern "C" fn(audio_mixer_id: u8) -> FfiOption<MixerChannelInfo>, pub audio_mixer_channel_set_level: extern "C" fn(audio_mixer_id: u8, level: u8) -> ApiResult<()>, pub audio_output_set_config: extern "C" fn(config: Config) -> ApiResult<()>, pub audio_output_get_config: extern "C" fn() -> ApiResult<Config>, pub audio_output_data: unsafe extern "C" fn(samples: FfiByteSlice<'_>) -> ApiResult<usize>, pub audio_output_get_space: extern "C" fn() -> ApiResult<usize>, pub audio_input_set_config: extern "C" fn(config: Config) -> ApiResult<()>, pub audio_input_get_config: extern "C" fn() -> ApiResult<Config>, pub audio_input_data: unsafe extern "C" fn(samples: FfiBuffer<'_>) -> ApiResult<usize>, pub audio_input_get_count: extern "C" fn() -> ApiResult<usize>, pub bus_select: extern "C" fn(peripheral_id: FfiOption<u8>), pub bus_get_info: extern "C" fn(peripheral_id: u8) -> FfiOption<PeripheralInfo>, pub bus_write_read: extern "C" fn(tx: FfiByteSlice<'_>, tx2: FfiByteSlice<'_>, rx: FfiBuffer<'_>) -> ApiResult<()>, pub bus_exchange: extern "C" fn(buffer: FfiBuffer<'_>) -> ApiResult<()>, pub bus_interrupt_status: extern "C" fn() -> u32, pub block_dev_get_info: extern "C" fn(device_id: u8) -> FfiOption<DeviceInfo>, pub block_dev_eject: extern "C" fn(device_id: u8) -> ApiResult<()>, pub block_write: extern "C" fn(device_id: u8, start_block: BlockIdx, num_blocks: u8, data: FfiByteSlice<'_>) -> ApiResult<()>, pub block_read: extern "C" fn(device_id: u8, start_block: BlockIdx, num_blocks: u8, data: FfiBuffer<'_>) -> ApiResult<()>, pub block_verify: extern "C" fn(device_id: u8, start_block: BlockIdx, num_blocks: u8, data: FfiByteSlice<'_>) -> ApiResult<()>, pub power_idle: extern "C" fn(), pub power_control: extern "C" fn(mode: FfiPowerMode) -> !, pub compare_and_swap_bool: extern "C" fn(value: &AtomicBool, old_value: bool, new_value: bool) -> bool,
}
Expand description

The BIOS API, expressed as a structure of function pointers.

All Neotron BIOSes should provide this structure to the OS initialisation function.

Fields§

§api_version_get: extern "C" fn() -> Version

Gets the version number of the BIOS API.

You need this value to determine which of the following API calls are valid in this particular version.

§bios_version_get: extern "C" fn() -> FfiString<'static>

Returns a pointer to a static string slice.

This string contains the version number and build string of the BIOS. For C compatibility this string is null-terminated and guaranteed to only contain ASCII characters (bytes with a value 127 or lower). We also pass the length (excluding the null) to make it easy to construct a Rust string. It is unspecified as to whether the string is located in Flash ROM or RAM (but it’s likely to be Flash ROM).

§serial_get_info: extern "C" fn(device_id: u8) -> FfiOption<DeviceInfo>

Get information about the Serial ports in the system.

Serial ports are ordered octet-oriented pipes. You can push octets into them using a ‘write’ call, and pull bytes out of them using a ‘read’ call. They have options which allow them to be configured at different speeds, or with different transmission settings (parity bits, stop bits, etc) - you set these with a call to SerialConfigure. They may physically be a MIDI interface, an RS-232 port or a USB-Serial port. There is no sense of ‘open’ or ‘close’ - that is an Operating System level design feature. These APIs just reflect the raw hardware, in a similar manner to the registers exposed by a memory-mapped UART peripheral.

§serial_configure: extern "C" fn(device_id: u8, config: Config) -> ApiResult<()>

Set the options for a given serial device. An error is returned if the options are invalid for that serial device.

§serial_write: extern "C" fn(device_id: u8, data: FfiByteSlice<'_>, timeout: FfiOption<Timeout>) -> ApiResult<usize>

Write bytes to a serial port. There is no sense of ‘opening’ or ‘closing’ the device - serial devices are always open. If the return value is Ok(n), the value n may be less than the size of the given buffer. If so, that means not all of the data could be transmitted - only the first n bytes were.

§serial_read: extern "C" fn(device_id: u8, data: FfiBuffer<'_>, timeout: FfiOption<Timeout>) -> ApiResult<usize>

Read bytes from a serial port. There is no sense of ‘opening’ or ‘closing’ the device - serial devices are always open. If the return value is Ok(n), the value n may be less than the size of the given buffer. If so, that means not all of the requested data could be received - only the first n bytes were (and hence only the first n bytes of the given buffer now contain data).

§time_clock_get: extern "C" fn() -> Time

Get the current wall time.

The Neotron BIOS does not understand time zones, leap-seconds or the Gregorian calendar. It simply stores time as an incrementing number of seconds since some epoch, and the number of video frames (at 60 Hz) since that second began. A day is assumed to be exactly 86,400 seconds long. This is a lot like POSIX time, except we have a different epoch

  • the Neotron epoch is 2000-01-01T00:00:00Z. It is highly recommend that you store UTC in the BIOS and use the OS to handle time-zones.

If the BIOS does not have a battery-backed clock, or if that battery has failed to keep time, the system starts up assuming it is the epoch.

§time_clock_set: extern "C" fn(time: Time)

Set the current wall time.

See time_get for a description of now the Neotron BIOS should handle time.

You only need to call this whenever you get a new sense of the current time (e.g. the user has updated the current time, or if you get a GPS fix). The BIOS should push the time out to the battery-backed Real Time Clock, if it has one.

§time_ticks_get: extern "C" fn() -> Ticks

Get the current monotonic system time.

This value will never go backwards and it should never wrap.

§time_ticks_per_second: extern "C" fn() -> Ticks

Report the system tick rate, in ticks-per-second.

§configuration_get: extern "C" fn(buffer: FfiBuffer<'_>) -> ApiResult<usize>

Get the configuration data block.

Configuration data is, to the BIOS, just a block of bytes of a given length. How it stores them is up to the BIOS - it could be EEPROM, or battery-backed SRAM.

§configuration_set: extern "C" fn(buffer: FfiByteSlice<'_>) -> ApiResult<()>

Set the configuration data block.

See configuration_get.

§video_is_valid_mode: extern "C" fn(mode: Mode) -> bool

Does this Neotron BIOS support this video mode?

§video_mode_needs_vram: extern "C" fn(mode: Mode) -> bool

Does this Neotron BIOS require extra VRAM for this mode to work?

If true returned here, you must pass some VRAM in the call to Api::video_set_mode, otherwise that function will return an error.

If false returned here, you can pass NULL to Api::video_set_mode.

§video_set_mode: unsafe extern "C" fn(mode: Mode, vram: *mut u32) -> ApiResult<()>

Switch to a new video mode, passing an optional pointer to some VRAM.

If the vram pointer is NULL, the BIOS will attempt to use any internal VRAM it has available. If it doesn’t have enough VRAM, you will get no picture.

§Safety

If a non-null vram value is given, it must be the start of a 32-bit aligned block which is at least frame_size_bytes() bytes in length

§video_get_mode: extern "C" fn() -> Mode

Returns the video mode the BIOS is currently in.

The OS should call this function immediately after start-up and note the value - this is the default video mode which can always be serviced without supplying extra RAM.

§video_get_framebuffer: extern "C" fn() -> *mut u32

Get the framebuffer address.

We can write through this address to the video framebuffer. The meaning of the data we write, and the size of the region we are allowed to write to, is a function of the current video mode (see video_get_mode).

This function will return null if the BIOS isn’t able to support the current video mode from its memory reserves. If that happens, you will need to use some OS RAM or Application RAM and provide that as a framebuffer to video_set_framebuffer. The BIOS will always be able to provide the ‘basic’ text buffer experience from reserves, so this function will never return null on start-up.

§video_wait_for_line: extern "C" fn(line: u16)

Wait for the next occurence of the specified video scan-line.

In general we must assume that the video memory is read top-to-bottom as the picture is being drawn on the monitor (e.g. via a VGA video signal). If you modify video memory during this drawing period there is a risk that the image on the monitor (however briefly) may contain some parts from before the modification and some parts from after. This can given rise to the tearing effect where it looks like the screen has been torn (or ripped) across because there is a discontinuity part-way through the image.

This function busy-waits until the video drawing has reached a specified scan-line on the video frame.

There is no error code here. If the line you ask for is beyond the number of visible scan-lines in the current video mode, it waits util the last visible scan-line is complete.

If you wait for the last visible line until drawing, you stand the best chance of your pixels operations on the video RAM being completed before scan-lines start being sent to the monitor for the next frame.

You can also use this for a crude 16.7 ms delay but note that some video modes run at 70 Hz and so this would then give you a 14.3ms second delay.

§video_get_palette: extern "C" fn(palette_idx: u8) -> FfiOption<RGBColour>

Get an entry from the colour palette.

Almost all video modes (except Chunky16 and Chunky32) use a video palette. This function returns the RGB colour for a given palette index.

If you ask for an entry that is beyond the capabilities of the current video mode, you get None.

§video_set_palette: extern "C" fn(palette_idx: u8, _: RGBColour)

Set an entry in the colour palette.

Almost all video modes (except Chunky16 and Chunky32) use a video palette. This function changes the RGB colour for a given palette index.

If you set an entry beyond what the current mode supports, the value is ignored.

§video_set_whole_palette: unsafe extern "C" fn(start: *const RGBColour, length: usize)

Sets all the entries in the colour palette at once.

Almost all video modes (except Chunky16 and Chunky32) use a video palette. This function changes all the RGB colours in the current palette.

If you pass a len beyond what the current mode supports, the extra values are ignored. The given buffer is copied so it doesn’t need to live beyond this function call.

§Safety

The value start must point to an array of RGBColour of length length.

§memory_get_region: extern "C" fn(region_index: u8) -> FfiOption<MemoryRegion>

Find out about regions of memory in the system.

The first region (index 0) must be the ‘application region’ which is defined to always start at address 0x2000_0400 (that is, 1 KiB into main SRAM) on a standard Cortex-M system. This application region stops just before the BIOS reserved memory, typically at the top of the internal SRAM.

Other regions may be located at other addresses (e.g. external DRAM or PSRAM).

The OS will always load non-relocatable applications into the bottom of Region 0. It can allocate OS specific structures from any other Region (if any), or from the top of Region 0 (although this reduces the maximum application space available). The OS will prefer lower numbered regions (other than Region 0), so faster memory should be listed first.

§hid_get_event: extern "C" fn() -> ApiResult<FfiOption<HidEvent>>

Get the next available HID event, if any.

This function doesn’t block. It will return Ok(None) if there is no event ready.

§hid_set_leds: extern "C" fn(leds: KeyboardLeds) -> ApiResult<()>

Control the keyboard LEDs.

§i2c_bus_get_info: extern "C" fn(bus_id: u8) -> FfiOption<BusInfo>

Get information about the I²C Buses in the system.

I²C Bus 0 should be the one connected to the Neotron Bus. I²C Bus 1 is typically the VGA DDC bus.

§i2c_write_read: extern "C" fn(bus_id: u8, i2c_device_address: u8, tx: FfiByteSlice<'_>, tx2: FfiByteSlice<'_>, rx: FfiBuffer<'_>) -> ApiResult<()>

Transact with a I²C Device on an I²C Bus

  • i2c_bus - Which I²C Bus to use
  • i2c_device_address - The 7-bit I²C Device Address
  • tx - the first list of bytes to send (use FfiByteSlice::empty() if not required)
  • tx2 - the second (and optional) list of bytes to send (use FfiByteSlice::empty() if not required)
  • rx - the buffer to fill with read data (use FfiBuffer::empty() if not required)
// Read 16 bytes from the start of an EEPROM with device address 0x65 on Bus 0
let mut buf = [0u8; 16];
let _ = (api.i2c_write_read)(0, 0x65, FfiByteSlice::new(&[0x00, 0x00]), FfiByteSlice::empty(), FfiBuffer::new(&mut buf));
// Write those bytes to somewhere else in an EEPROM with device address 0x65 on Bus 0
// You can see now why it's useful to have *two* TX buffers available
let _ = (api.i2c_write_read)(0, 0x65, FfiByteSlice::new(&[0x00, 0x10]), FfiByteSlice::new(&buf), FfiBuffer::empty());
§audio_mixer_channel_get_info: extern "C" fn(audio_mixer_id: u8) -> FfiOption<MixerChannelInfo>

Get information about the Audio Mixer channels

§audio_mixer_channel_set_level: extern "C" fn(audio_mixer_id: u8, level: u8) -> ApiResult<()>

Set an Audio Mixer level

§audio_output_set_config: extern "C" fn(config: Config) -> ApiResult<()>

Configure the audio output.

If accepted, the audio output FIFO is flushed and the changes apply immediately. If not accepted, an error is returned.

It is not currently possible to enumerate all the possible sample rates - you just have to try a variety of well know configurations to see which ones work.

Note that if your desired sample rate cannot be exactly accepted, but is within some tolerance, this function will still succeed. Therefore you should call audio_output_get_config to get the precise sample rate that the system is actually using if that matters to your application. For example, you might ask for 48,000 Hz but due to the system clock frequency and other factors, a sample rate of 48,018 Hz might actually be achieved. Regardless, to avoid buffer underflows you should supply as many samples as audio_output_get_space says you need, not what you think you need based on the sample rate you think you have.

§audio_output_get_config: extern "C" fn() -> ApiResult<Config>

Get the audio output’s current configuration.

§audio_output_data: unsafe extern "C" fn(samples: FfiByteSlice<'_>) -> ApiResult<usize>

Send audio samples to the output FIFO.

The format of the samples (little-endian, 16-bit, etc), depends on the current output configuration. Note that the slice is in bytes and there will be between one and four bytes per sample depending on the format.

This function won’t block, but it will return how much data was accepted. The given samples will be copied and so the buffer is free to re-use once the function returns. To avoid buffer underflows you should supply as many samples as audio_output_get_space says you need, not what you think you need based on the sample rate you think you have (as there will always be some error margin on that).

If the buffer underflows, silence is played out.

There is only one hardware output stream so any mixing has to be performed in software by the OS.

§audio_output_get_space: extern "C" fn() -> ApiResult<usize>

Get audio buffer space.

How many samples in the current format can be sent to audio_output_data without blocking?

§audio_input_set_config: extern "C" fn(config: Config) -> ApiResult<()>

Configure the audio input.

If accepted, the audio input FIFO is flushed and the changes apply immediately. If not accepted, an error is returned.

It is not currently possible to enumerate all the possible sample rates - you just have to try a variety of well know configurations to see which ones work.

Note that if your desired sample rate cannot be exactly accepted, but is within some tolerance, this function will still succeed. Therefore you should call audio_output_get_config to get the precise sample rate that the system is actually using if that matters to your application. For example, you might ask for 48,000 Hz but due to the system clock frequency and other factors, a sample rate of 48,018 Hz might actually be achieved.

§audio_input_get_config: extern "C" fn() -> ApiResult<Config>

Get the audio input’s current configuration.

§audio_input_data: unsafe extern "C" fn(samples: FfiBuffer<'_>) -> ApiResult<usize>

Get 16-bit stereo audio from the input FIFO.

The format of the samples (little-endian, 16-bit, etc), depends on the current output configuration. Note that the slice is in bytes and there will be between one and four bytes per sample depending on the format.

This function won’t block, but it will return how much data was actually written to the buffer.

If you don’t call it often enough, there will be a buffer overflow and audio will be dropped.

§audio_input_get_count: extern "C" fn() -> ApiResult<usize>

Get audio buffer space.

How many samples in the current format can be read right now using audio_input_data?

§bus_select: extern "C" fn(peripheral_id: FfiOption<u8>)

Select a Neotron Bus Peripheral. This drives the SPI chip-select line low for that peripheral. Selecting a peripheral de-selects any other peripherals. Select peripheral ‘None’ to select no peripherals. If you lock the bus then interrupt routines that need the bus are blocked and must be deferred. Therefore you should try and release the bus whilst waiting for things to happen (if your peripheral can tolerate the CS line being de-activated at that time).

§bus_get_info: extern "C" fn(peripheral_id: u8) -> FfiOption<PeripheralInfo>

Find out some details about each particular Neotron Bus Peripheral.

§bus_write_read: extern "C" fn(tx: FfiByteSlice<'_>, tx2: FfiByteSlice<'_>, rx: FfiBuffer<'_>) -> ApiResult<()>

Transact with the currently selected Neotron Bus Peripheral.

You should select a peripheral with bus_select first, however you can send unselected traffic (e.g. to configure an SD Card into SPI mode).

  • tx - the first list of bytes to send (use &[] if not required)
  • tx2 - the second (and optional) list of bytes to send (use &[] if not required)
  • rx - the buffer to fill with read data (use &mut [] if not required)

Because SPI is full-duplex, we discard incoming bytes during the TX portion. We must also clock out something during the RX portion, and we chose 0xFF bytes. If that doesn’t work, use bus_exchange.

// Grab Peripheral 1 on the bus
let _ = (api.bus_select)(FfiOption::Some(1));
// Read 16 bytes from Register 0 of the selected peripheral
let mut buf = [0u8; 16];
let _ = (api.bus_write_read)(FfiByteSlice::new(&[0, 16]), FfiByteSlice::empty(), FfiBuffer::new(&mut buf));
// Write those bytes to Register 2. You can see now why it's useful to
// have *two* TX buffers in the API
let _ = (api.bus_write_read)(FfiByteSlice::new(&[2, 16]), FfiByteSlice::new(&buf), FfiBuffer::empty());
// Release the bus
let _ = (api.bus_select)(FfiOption::None);
§bus_exchange: extern "C" fn(buffer: FfiBuffer<'_>) -> ApiResult<()>

Exchange bytes with the currently selected Neotron Bus Peripheral.

You should select a peripheral with bus_select first, however you can send unselected traffic (e.g. to configure an SD Card into SPI mode).

SPI is full-duplex, and this routine clocks out the bytes in buffer one at a time, and replaces them with the bytes received from the peripheral.

// Grab Peripheral 1 on the bus
let _ = (api.bus_select)(FfiOption::Some(1));
// Exchange four bytes with the peripheral
let mut buf = [0, 1, 2, 3];
let _ = (api.bus_exchange)(FfiBuffer::new(&mut buf));
// buf now contains whatever the peripheral sent us.
// Release the bus
let _ = (api.bus_select)(FfiOption::None);
§bus_interrupt_status: extern "C" fn() -> u32

Get bus interrupt status.

Up to 32 interrupts can be returned as a single 32-bit value. A bit is set when the interrupt is pending. There is no masking - ignore the bits you don’t care about.

§block_dev_get_info: extern "C" fn(device_id: u8) -> FfiOption<DeviceInfo>

Get information about the Block Devices in the system.

Block Devices are also known as disk drives. They can be read from (and often written to) but only in units called blocks or sectors.

The BIOS should enumerate removable devices first, followed by fixed devices.

The set of devices is not expected to change at run-time - removal of media is indicated with a boolean field in the block_dev::DeviceInfo structure.

§block_dev_eject: extern "C" fn(device_id: u8) -> ApiResult<()>

Eject a disk from the drive.

Will return an error if this device is not removable. Does not return an error if the drive is already empty.

§block_write: extern "C" fn(device_id: u8, start_block: BlockIdx, num_blocks: u8, data: FfiByteSlice<'_>) -> ApiResult<()>

Write one or more sectors to a block device.

The function will block until all data is written. The array pointed to by data must be num_blocks * block_size in length, where block_size is given by block_dev_get_info.

There are no requirements on the alignment of data but if it is aligned, the BIOS may be able to use a higher-performance code path.

§block_read: extern "C" fn(device_id: u8, start_block: BlockIdx, num_blocks: u8, data: FfiBuffer<'_>) -> ApiResult<()>

Read one or more sectors to a block device.

The function will block until all data is read. The array pointed to by data must be num_blocks * block_size in length, where block_size is given by block_dev_get_info.

There are no requirements on the alignment of data but if it is aligned, the BIOS may be able to use a higher-performance code path.

§block_verify: extern "C" fn(device_id: u8, start_block: BlockIdx, num_blocks: u8, data: FfiByteSlice<'_>) -> ApiResult<()>

Verify one or more sectors on a block device (that is read them and check they match the given data).

The function will block until all data is verified. The array pointed to by data must be num_blocks * block_size in length, where block_size is given by block_dev_get_info.

There are no requirements on the alignment of data but if it is aligned, the BIOS may be able to use a higher-performance code path.

§power_idle: extern "C" fn()

The OS will call this function when it’s idle.

On a microcontroller, this will wait for interrupts. Running in an emulator, this will sleep the thread for a while.

§power_control: extern "C" fn(mode: FfiPowerMode) -> !

The OS will call this function to control power on this system.

This function will not return, because the system will be switched off before it can return. In the event on an error, this function will hang instead.

§compare_and_swap_bool: extern "C" fn(value: &AtomicBool, old_value: bool, new_value: bool) -> bool

Performs a compare-and-swap on value.

  • If value == old_value, sets value = new_value and returns true
  • If value != old_value, returns false

Auto Trait Implementations§

§

impl RefUnwindSafe for Api

§

impl Send for Api

§

impl Sync for Api

§

impl Unpin for Api

§

impl UnwindSafe for Api

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.