Skip to content

Commit e46b0ef

Browse files
Merge pull request #27 from Neotron-Compute/use-neotron-ffi
Use neotron FFI crate
2 parents c9e5910 + 9ac868f commit e46b0ef

File tree

8 files changed

+82
-363
lines changed

8 files changed

+82
-363
lines changed

Cargo.toml

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
[package]
2-
name = "neotron-common-bios"
3-
version = "0.8.0"
42
authors = ["Jonathan 'theJPster' Pallant <[email protected]>"]
5-
edition = "2018"
63
description = "Common BIOS code and API for all Neotron systems."
7-
license = "GPL-3.0-or-later"
8-
repository = "https://github.com/neotron-compute/neotron-common-bios.git"
4+
edition = "2018"
95
homepage = "https://github.com/neotron-compute/neotron-common-bios"
6+
license = "GPL-3.0-or-later"
7+
name = "neotron-common-bios"
108
readme = "README.md"
9+
repository = "https://github.com/neotron-compute/neotron-common-bios.git"
10+
version = "0.8.0"
1111

1212
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1313

1414
[dependencies]
15-
chrono = { version = "0.4", default-features=false }
15+
chrono = {version = "0.4", default-features = false}
16+
neotron-ffi = "0.1"
1617
pc-keyboard = "0.7"

src/audio.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ pub enum Direction {
8989
#[derive(Debug, Clone, PartialEq, Eq)]
9090
pub struct MixerChannelInfo {
9191
/// The name of this Audio Mixer Channel (e.g. `Line In`)
92-
pub name: crate::ApiString<'static>,
92+
pub name: crate::FfiString<'static>,
9393
/// Is this an Input or an Output?
9494
pub direction: Direction,
9595
/// What value of `current_level` gives the loudest audio? All values

src/block_dev.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ pub enum DeviceType {
5555
pub struct DeviceInfo {
5656
/// Some human-readable name for this block device (e.g. `SdCard0` or
5757
/// `CF1`)
58-
pub name: crate::ApiString<'static>,
58+
pub name: crate::FfiString<'static>,
5959
/// The kind of block device this is.
6060
pub device_type: DeviceType,
6161
/// The size of an addressable block, in bytes.

src/bus.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ pub enum PeripheralKind {
5656
#[derive(Debug, Clone, Eq, PartialEq)]
5757
pub struct PeripheralInfo {
5858
/// A name, such as `slot0`
59-
pub name: crate::ApiString<'static>,
59+
pub name: crate::FfiString<'static>,
6060
/// The kind of peripheral
6161
pub kind: PeripheralKind,
6262
}

src/i2c.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
pub struct BusInfo {
4343
/// Some human-readable name for this I²C device (e.g. `I²C0` or
4444
/// `DDC0`)
45-
pub name: crate::ApiString<'static>,
45+
pub name: crate::FfiString<'static>,
4646
}
4747

4848
// ============================================================================

src/lib.rs

Lines changed: 69 additions & 59 deletions
Large diffs are not rendered by default.

src/serial.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ pub struct Config {
140140
pub struct DeviceInfo {
141141
/// Some human-readable name for this serial device (e.g. `RS232` or
142142
/// `USB0`)
143-
pub name: crate::ApiString<'static>,
143+
pub name: crate::FfiString<'static>,
144144
/// The type of this serial device
145145
pub device_type: DeviceType,
146146
}

src/types.rs

Lines changed: 1 addition & 293 deletions
Original file line numberDiff line numberDiff line change
@@ -60,65 +60,11 @@ pub enum Error {
6060
BlockOutOfBounds,
6161
}
6262

63-
/// All API functions which can fail return this type. We don't use the
64-
/// `Result` type from the standard library because that isn't FFI safe and
65-
/// may change layout between compiler versions.
66-
#[repr(C)]
67-
pub enum Result<T> {
68-
/// The operation succeeded (the same as `core::result::Result::Ok`).
69-
Ok(T),
70-
/// The operation failed (the same as `core::result::Result::Err`).
71-
Err(Error),
72-
}
73-
74-
/// All API functions which take/return optional values return this type. We
75-
/// don't use the `Option` type from the standard library because that isn't
76-
/// FFI safe and may change layout between compiler versions.
77-
#[repr(C)]
78-
pub enum Option<T> {
79-
/// There is some data (the same as `core::option::Option::Some`)
80-
Some(T),
81-
/// There is no data (the same as `core::option::Option::None`)
82-
None,
83-
}
84-
8563
/// Describes a period of time, after which the BIOS should give up.
8664
#[repr(C)]
8765
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
8866
pub struct Timeout(u32);
8967

90-
/// A Rust UTF-8 string, but compatible with FFI. Assume the lifetime is only
91-
/// valid until the callee returns to the caller. Is not null-terminated.
92-
#[repr(C)]
93-
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
94-
pub struct ApiString<'a>(ApiByteSlice<'a>);
95-
96-
/// A Rust u8 slice, but compatible with FFI. Assume the lifetime is only valid
97-
/// until the callee returns to the caller.
98-
#[repr(C)]
99-
#[derive(Clone)]
100-
pub struct ApiByteSlice<'a> {
101-
/// A pointer to the data
102-
pub data: *const u8,
103-
/// The number of bytes we are pointing at
104-
pub data_len: usize,
105-
/// A phantom object to hold the lifetime
106-
_phantom: core::marker::PhantomData<&'a [u8]>,
107-
}
108-
109-
/// A Rust u8 mutable slice, but compatible with FFI. Assume the lifetime is
110-
/// only valid until the callee returns to the caller.
111-
#[repr(C)]
112-
#[derive(Clone)]
113-
pub struct ApiBuffer<'a> {
114-
/// A pointer to where the data can be put
115-
pub data: *mut u8,
116-
/// The maximum number of bytes we can store in this buffer
117-
pub data_len: usize,
118-
/// A phantom object to hold the lifetime
119-
_phantom: core::marker::PhantomData<&'a [u8]>,
120-
}
121-
12268
/// Represents an instant in time between 2000-01-01T00:00:00Z and
12369
/// 2136-02-07T06:28:16Z.
12470
#[repr(C)]
@@ -165,61 +111,8 @@ pub struct MemoryRegion {
165111

166112
// OsStartFn
167113

168-
// Error
169-
170-
impl<T> Result<T> {
171-
/// Obtain the inner value, or panic - just like `core::Result::unwrap`.
172-
pub fn unwrap(self) -> T {
173-
let r: core::result::Result<T, Error> = self.into();
174-
r.unwrap()
175-
}
176-
}
177-
178-
impl<T> From<core::result::Result<T, Error>> for Result<T> {
179-
fn from(value: core::result::Result<T, Error>) -> Self {
180-
match value {
181-
Ok(inner) => Result::Ok(inner),
182-
Err(inner) => Result::Err(inner),
183-
}
184-
}
185-
}
186-
187-
impl<T> From<Result<T>> for core::result::Result<T, Error> {
188-
fn from(value: Result<T>) -> Self {
189-
match value {
190-
Result::Ok(inner) => core::result::Result::Ok(inner),
191-
Result::Err(inner) => core::result::Result::Err(inner),
192-
}
193-
}
194-
}
195-
196-
impl<T> Option<T> {
197-
/// Obtain the inner value, or panic - just like `core::Option::unwrap`.
198-
pub fn unwrap(self) -> T {
199-
let o: core::option::Option<T> = self.into();
200-
o.unwrap()
201-
}
202-
}
203-
204-
impl<T> From<core::option::Option<T>> for Option<T> {
205-
fn from(value: core::option::Option<T>) -> Self {
206-
match value {
207-
Some(inner) => Option::Some(inner),
208-
None => Option::None,
209-
}
210-
}
211-
}
212-
213-
impl<T> From<Option<T>> for core::option::Option<T> {
214-
fn from(value: Option<T>) -> Self {
215-
match value {
216-
Option::Some(inner) => core::option::Option::Some(inner),
217-
Option::None => core::option::Option::None,
218-
}
219-
}
220-
}
221-
222114
// Timeout
115+
223116
impl Timeout {
224117
/// Create a new timeout, in milliseconds.
225118
pub fn new_ms(milliseconds: u32) -> Timeout {
@@ -238,191 +131,6 @@ impl Timeout {
238131
}
239132
}
240133

241-
// ApiString
242-
243-
impl<'a> ApiString<'a> {
244-
/// Create a new string slice we can send over the FFI.
245-
pub fn new(s: &'a str) -> ApiString<'a> {
246-
ApiString(ApiByteSlice::new(s.as_bytes()))
247-
}
248-
249-
/// Turn this FFI string into a Rust string slice.
250-
pub fn as_str(&'a self) -> &'a str {
251-
unsafe { core::str::from_utf8_unchecked(self.0.as_slice()) }
252-
}
253-
}
254-
255-
impl<'a> From<&'a str> for ApiString<'a> {
256-
/// Create a new FFI string from a string slice.
257-
fn from(input: &'a str) -> ApiString<'a> {
258-
ApiString::new(input)
259-
}
260-
}
261-
262-
impl core::fmt::Debug for ApiString<'_> {
263-
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
264-
let buffer = unsafe { core::slice::from_raw_parts(self.0.data, self.0.data_len) };
265-
let s = unsafe { core::str::from_utf8_unchecked(buffer) };
266-
write!(f, "{:?}", s)
267-
}
268-
}
269-
270-
impl core::fmt::Display for ApiString<'_> {
271-
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
272-
let buffer = unsafe { core::slice::from_raw_parts(self.0.data, self.0.data_len) };
273-
let s = unsafe { core::str::from_utf8_unchecked(buffer) };
274-
write!(f, "{}", s)
275-
}
276-
}
277-
278-
// ApiByteSlice
279-
280-
impl<'a> ApiByteSlice<'a> {
281-
/// Create a new byte slice we can send over the FFI.
282-
pub fn new(s: &'a [u8]) -> ApiByteSlice<'a> {
283-
ApiByteSlice {
284-
data: s.as_ptr(),
285-
data_len: s.len(),
286-
_phantom: core::marker::PhantomData,
287-
}
288-
}
289-
290-
/// Make an empty slice.
291-
pub fn empty() -> ApiByteSlice<'static> {
292-
static EMPTY: &[u8] = &[];
293-
ApiByteSlice::new(EMPTY)
294-
}
295-
296-
/// Turn this byte slice into a Rust byte slice.
297-
pub fn as_slice(&self) -> &[u8] {
298-
unsafe { core::slice::from_raw_parts(self.data, self.data_len) }
299-
}
300-
}
301-
302-
impl core::fmt::Debug for ApiByteSlice<'_> {
303-
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
304-
let slice = self.as_slice();
305-
write!(f, "[ ")?;
306-
if let Some((last, rest)) = slice.split_last() {
307-
for i in rest.iter() {
308-
write!(f, "0x{:02x}, ", i)?;
309-
}
310-
write!(f, "0x{:02x} ", last)?;
311-
}
312-
write!(f, "]")
313-
}
314-
}
315-
316-
impl<'a> From<&'a [u8]> for ApiByteSlice<'a> {
317-
/// Convert from a Rust byte slice into an FFI compatible byte slice
318-
fn from(input: &'a [u8]) -> ApiByteSlice<'a> {
319-
ApiByteSlice::new(input)
320-
}
321-
}
322-
323-
impl<'a> core::cmp::PartialEq for ApiByteSlice<'a> {
324-
/// Check if two ApiByteSlices are equal.
325-
///
326-
/// We just make some actual slices and compare then.
327-
fn eq(&self, rhs: &Self) -> bool {
328-
if self.data_len != rhs.data_len {
329-
return false;
330-
}
331-
let this_slice = self.as_slice();
332-
let that_slice = rhs.as_slice();
333-
this_slice == that_slice
334-
}
335-
}
336-
337-
impl<'a> core::cmp::Eq for ApiByteSlice<'a> {}
338-
339-
impl<'a> core::cmp::Ord for ApiByteSlice<'a> {
340-
/// Compare two ApiByteSlices.
341-
///
342-
/// We just make some actual slices and compare then.
343-
fn cmp(&self, rhs: &Self) -> core::cmp::Ordering {
344-
let this_slice = self.as_slice();
345-
let that_slice = rhs.as_slice();
346-
this_slice.cmp(that_slice)
347-
}
348-
}
349-
350-
impl<'a> core::cmp::PartialOrd for ApiByteSlice<'a> {
351-
/// Compare two ApiByteSlices.
352-
///
353-
/// We are `Ord` so we can defer to that.
354-
fn partial_cmp(&self, rhs: &Self) -> core::option::Option<core::cmp::Ordering> {
355-
Some(self.cmp(rhs))
356-
}
357-
}
358-
359-
// ApiBuffer
360-
361-
impl<'a> ApiBuffer<'a> {
362-
/// Create a new buffer we can send over the FFI.
363-
///
364-
/// This buffer is a mutable borrow of some storage space allocated
365-
/// elsewhere. If you are given this type in an API, assume it is only
366-
/// valid for as long as the function call you were given in it.
367-
pub fn new(s: &'a mut [u8]) -> ApiBuffer<'a> {
368-
ApiBuffer {
369-
data: s.as_mut_ptr(),
370-
data_len: s.len(),
371-
_phantom: core::marker::PhantomData,
372-
}
373-
}
374-
375-
/// Make an empty slice.
376-
pub fn empty() -> ApiBuffer<'static> {
377-
ApiBuffer {
378-
data: core::ptr::null_mut(),
379-
data_len: 0,
380-
_phantom: core::marker::PhantomData,
381-
}
382-
}
383-
384-
/// Turn this buffer into a Rust byte slice.
385-
pub fn as_slice(&self) -> &[u8] {
386-
if self.data.is_null() {
387-
&[]
388-
} else {
389-
unsafe { core::slice::from_raw_parts(self.data, self.data_len) }
390-
}
391-
}
392-
393-
/// Turn this buffer into a Rust mutable byte slice.
394-
///
395-
/// You will get `None` if the buffer is empty (i.e. has zero length).
396-
pub fn as_mut_slice(&mut self) -> core::option::Option<&mut [u8]> {
397-
if self.data.is_null() {
398-
None
399-
} else {
400-
Some(unsafe { core::slice::from_raw_parts_mut(self.data, self.data_len) })
401-
}
402-
}
403-
}
404-
405-
impl core::fmt::Debug for ApiBuffer<'_> {
406-
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
407-
let slice = self.as_slice();
408-
write!(f, "[ ")?;
409-
if let Some((last, rest)) = slice.split_last() {
410-
for i in rest.iter() {
411-
write!(f, "0x{:02x}, ", i)?;
412-
}
413-
write!(f, "0x{:02x} ", last)?;
414-
}
415-
write!(f, "]")
416-
}
417-
}
418-
419-
impl<'a> From<&'a mut [u8]> for ApiBuffer<'a> {
420-
/// Convert from a Rust byte slice into an FFI compatible byte slice
421-
fn from(input: &'a mut [u8]) -> ApiBuffer<'a> {
422-
ApiBuffer::new(input)
423-
}
424-
}
425-
426134
// Time
427135

428136
impl core::fmt::Display for Time {

0 commit comments

Comments
 (0)