neotron_api/
lib.rs

1//! The Neotron API
2//!
3//! Defines the API supplied to applications that run on Neotron OS. This API is
4//! provided in the form of a rust `struct Api`, where every field is a function
5//! pointer.
6
7#![no_std]
8
9// ============================================================================
10// Imports
11// ============================================================================
12
13pub mod dir;
14pub mod file;
15pub mod path;
16
17pub use neotron_ffi::{FfiBuffer, FfiByteSlice, FfiString};
18
19// ============================================================================
20// Constants
21// ============================================================================
22
23/// Maximum length of a filename (with no directory components), including the
24/// extension.
25pub const MAX_FILENAME_LEN: usize = 11;
26
27// ============================================================================
28// Types
29// ============================================================================
30
31/// The result type for any SDK API function.
32///
33/// Like a [`neotron_ffi::FfiResult`] but the error type is [`Error`].
34pub type Result<T> = neotron_ffi::FfiResult<T, Error>;
35
36/// The syscalls provided by the Neotron OS to a Neotron Application.
37#[repr(C)]
38pub struct Api {
39    /// Open a file, given a path as UTF-8 string.
40    ///
41    /// If the file does not exist, or is already open, it returns an error.
42    ///
43    /// Path may be relative to current directory, or it may be an absolute
44    /// path.
45    ///
46    /// # Limitations
47    ///
48    /// * You cannot open a file if it is currently open.
49    /// * Paths must confirm to the rules for the filesystem for the given drive.
50    /// * Relative paths are taken relative to the current directory (see `Api::chdir`).
51    pub open: extern "C" fn(path: FfiString, flags: file::Flags) -> Result<file::Handle>,
52    /// Close a previously opened file.
53    ///
54    /// Closing a file is important, as only this action will cause the
55    /// directory entry for the file to be updated. Crashing the system without
56    /// closing a file may cause the directory entry to be incorrect, and you
57    /// may need to run `CHKDSK` (or similar) on your disk to fix it.
58    pub close: extern "C" fn(fd: file::Handle) -> Result<()>,
59    /// Write to an open file handle, blocking until everything is written.
60    ///
61    /// Some files do not support writing and will produce an error. You will
62    /// also get an error if you run out of disk space.
63    ///
64    /// The `buffer` is only borrowed for the duration of the function call and
65    /// is then forgotten.
66    pub write: extern "C" fn(fd: file::Handle, buffer: FfiByteSlice) -> Result<()>,
67    /// Read from an open file, returning how much was actually read.
68    ///
69    /// You might get less data than you asked for. If you do an `Api::read` and
70    /// you are already at the end of the file you will get
71    /// `Err(Error::EndOfFile)`.
72    ///
73    /// Data is stored to the given `buffer. The `buffer` is only borrowed for
74    /// the duration of the function call and is then forgotten.
75    pub read: extern "C" fn(fd: file::Handle, buffer: FfiBuffer) -> Result<usize>,
76    /// Move the file offset (for the given file handle) to the given position.
77    ///
78    /// Some files do not support seeking and will produce an error.
79    pub seek_set: extern "C" fn(fd: file::Handle, position: u64) -> Result<()>,
80    /// Move the file offset (for the given file handle) relative to the current position.
81    ///
82    /// Returns the new file offset.
83    ///
84    /// Some files do not support seeking and will produce an error.
85    pub seek_cur: extern "C" fn(fd: file::Handle, offset: i64) -> Result<u64>,
86    /// Move the file offset (for the given file handle) to the end of the file
87    ///
88    /// Returns the new file offset.
89    ///
90    /// Some files do not support seeking and will produce an error.
91    pub seek_end: extern "C" fn(fd: file::Handle) -> Result<u64>,
92    /// Rename a file.
93    ///
94    /// # Limitations
95    ///
96    /// * You cannot rename a file if it is currently open.
97    /// * You cannot rename a file where the `old_path` and the `new_path` are
98    /// not on the same drive.
99    /// * Paths must confirm to the rules for the filesystem for the given drive.
100    pub rename: extern "C" fn(old_path: FfiString, new_path: FfiString) -> Result<()>,
101    /// Perform a special I/O control operation.
102    pub ioctl: extern "C" fn(fd: file::Handle, command: u64, value: u64) -> Result<u64>,
103    /// Open a directory, given a path as a UTF-8 string.
104    pub opendir: extern "C" fn(path: FfiString) -> Result<dir::Handle>,
105    /// Close a previously opened directory.
106    pub closedir: extern "C" fn(dir: dir::Handle) -> Result<()>,
107    /// Read from an open directory
108    pub readdir: extern "C" fn(dir: dir::Handle) -> Result<dir::Entry>,
109    /// Get information about a file.
110    pub stat: extern "C" fn(path: FfiString) -> Result<file::Stat>,
111    /// Get information about an open file.
112    pub fstat: extern "C" fn(fd: file::Handle) -> Result<file::Stat>,
113    /// Delete a file.
114    ///
115    /// # Limitations
116    ///
117    /// * You cannot delete a file if it is currently open.
118    pub deletefile: extern "C" fn(path: FfiString) -> Result<()>,
119    /// Delete a directory.
120    ///
121    /// # Limitations
122    ///
123    /// * You cannot delete a root directory.
124    /// * You cannot delete a directory that has any files or directories in it.
125    pub deletedir: extern "C" fn(path: FfiString) -> Result<()>,
126    /// Change the current directory.
127    ///
128    /// Relative file paths (e.g. passed to `Api::open`) are taken to be relative to the current directory.
129    ///
130    /// Unlike on MS-DOS, there is only one current directory for the whole
131    /// system, not one per drive.
132    pub chdir: extern "C" fn(path: FfiString) -> Result<()>,
133    /// Change the current directory to the given open directory.
134    ///
135    /// Unlike on MS-DOS, there is only one current directory for the whole
136    /// system, not one per drive.
137    pub dchdir: extern "C" fn(dir: dir::Handle) -> Result<()>,
138    /// Get the current directory.
139    ///
140    /// The current directory is stored as UTF-8 into the given buffer. The
141    /// function returns the number of bytes written to the buffer, or an error.
142    /// If the function did not return an error, the buffer can be assumed to
143    /// contain a valid file path. That path will not be null terminated.
144    pub pwd: extern "C" fn(path: FfiBuffer) -> Result<usize>,
145    /// Allocate some memory.
146    ///
147    /// * `size` - the number of bytes required
148    /// * `alignment` - the returned address will have this alignment, or
149    ///   better. For example, pass `4` if you are allocating an array of `u32`.
150    pub malloc: extern "C" fn(size: usize, alignment: usize) -> Result<*mut core::ffi::c_void>,
151    /// Free some previously allocated memory.
152    ///
153    /// You must pass the same `size` and `alignment` values that you passed to `malloc`.
154    pub free: extern "C" fn(ptr: *mut core::ffi::c_void, size: usize, alignment: usize),
155}
156
157/// The type of the entry function for an application
158///
159/// * `api` is a pointer to the [`Api`] callback table
160/// * `argc` is the number of arguments passed. If this is non-zero, then `argv`
161///   must be non-null.
162/// * `argv` is a pointer to the start of an array of arguments to the program.
163///   Every item in that array is a [`FfiString`]. There are `argc` items in the
164///   array.
165///
166/// The function should return `0` on success, or anything else to indicate an
167/// error.
168pub type AppStartFn = extern "C" fn(api: *const Api, argc: usize, argv: *const FfiString) -> i32;
169
170/// Describes how something has failed
171#[repr(C)]
172#[derive(Debug, Copy, Clone, PartialEq, Eq)]
173pub enum Error {
174    /// The given file/directory path was not found
175    NotFound,
176    /// Tried to write to a read-only file
177    FileReadOnly,
178    /// Reached the end of the file
179    EndOfFile,
180    /// The API has not been implemented
181    Unimplemented,
182    /// An invalid argument was given to the API
183    InvalidArg,
184    /// A bad handle was given to the API
185    BadHandle,
186    /// An device-specific error occurred. Look at the BIOS source for more details.
187    DeviceSpecific,
188    /// The OS does not have enough memory
189    OutOfMemory,
190    /// The given path was invalid
191    InvalidPath,
192}
193
194// ============================================================================
195// Functions
196// ============================================================================
197
198// None
199
200// ============================================================================
201// Tests
202// ============================================================================
203
204// None
205
206// ============================================================================
207// End of File
208// ============================================================================