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// ============================================================================