Add guide on how to write modules
This commit is contained in:
parent
348389f745
commit
4e3101f5f3
1 changed files with 100 additions and 0 deletions
100
doc/src/03020-writing-modules.md
Normal file
100
doc/src/03020-writing-modules.md
Normal file
|
@ -0,0 +1,100 @@
|
|||
# Writing an imag module
|
||||
|
||||
So you want to write a module for imag.
|
||||
That's nice.
|
||||
|
||||
This guide helps you getting started.
|
||||
It also can help you understanding how imag modules work, so even if you do
|
||||
not want to write a full new module, but extend or alter one, this guide may
|
||||
help you.
|
||||
|
||||
|
||||
## Data layout
|
||||
|
||||
First, you have to think about what data you want to store.
|
||||
What functionality do you want to provide and what data that creates.
|
||||
|
||||
In this example, we're writing a module that stores numbers. We're writing the
|
||||
appropriate library for that as well as a commandline frontend.
|
||||
|
||||
|
||||
## libimagnumberstorage
|
||||
|
||||
We're writing a `libimagnumberstorage` which provides the core functionality
|
||||
of our module: Storing numbers.
|
||||
|
||||
That library can then be used by other library authors and by the commandline
|
||||
interface implementation.
|
||||
|
||||
### Setup
|
||||
|
||||
So what do we need to do to write this library:
|
||||
|
||||
1. Create a new "lib" crate.
|
||||
Because we're writing a "domain" library, we're doing this in the
|
||||
`lib/domain` subdirectory:
|
||||
`cd lib/domain; cargo new --lib libimagnumberstorage`.
|
||||
1. After creating the library, we have to add the new library to the
|
||||
`/Cargo.toml` field and add the missing metadata in the new
|
||||
`/lib/domain/libimagnumberstorage/Cargo.toml` file.
|
||||
|
||||
That was the setup part.
|
||||
Now we can implement our functionality.
|
||||
For that, we need to _extend_ two types from `libimagstore`, so we have our
|
||||
first dependency here.
|
||||
|
||||
### Dependencies to other libraries
|
||||
|
||||
3. Put `libimagstore` as a dependency in the
|
||||
`/lib/domain/libimagnumberstorage/Cargo.toml` file.
|
||||
By using
|
||||
`libimagstore = { version = "0.7.0", path = "../../../lib/core/libimagstore" }`
|
||||
we automatically get all the goodness of Cargo, so that releases
|
||||
automagically work as expected, but when developing locally, the local
|
||||
version of `libimagstore` is used.
|
||||
Of course, the `version` has to be the latest released version.
|
||||
4. For error handling, we also need to import `libimagerror`.
|
||||
5. For easy header-editing, we import `toml` and `toml-query`.
|
||||
6. For error-type creating, we import `error-chain`.
|
||||
|
||||
### Interface
|
||||
|
||||
7. Then, we have to _extend_ two types:
|
||||
1. `libimagstore::store::Store` has to be extended so we can implement a
|
||||
CRUD interface for our special entries.
|
||||
1. `libimagstore::store::Entry` has to be extended so we can get our
|
||||
stored numbers in a convenient way.
|
||||
|
||||
Our interface should roughly look like this:
|
||||
|
||||
```
|
||||
store.get_stored_number("5") -> Result<FileLockEntry, _>
|
||||
store.store_number("5") -> Result<FileLockEntry, _>
|
||||
store.delete_number("5") -> Result<(), _>
|
||||
```
|
||||
|
||||
You notice that the `Store` returns `FileLockEntry` objects rather than
|
||||
`Entry` objects.
|
||||
And that's ok. A `FileLockEntry` is a `Entry`, but ensures that we are the
|
||||
only ones editing that entry.
|
||||
So, we have to implement our number-storing-interface on `Entry` as well:
|
||||
|
||||
```
|
||||
entry.get_number() -> Result<usize>
|
||||
entry.set_number(usize) -> Result<()>
|
||||
```
|
||||
|
||||
All those "extensions" are implemented as traits which are then implemented
|
||||
for `Store` and `Entry`.
|
||||
|
||||
Normally, we create new files for that, as well as for the error types we need:
|
||||
|
||||
* `/lib/domain/libimagnumberstorage/src/store.rs`
|
||||
* `/lib/domain/libimagnumberstorage/src/entry.rs`
|
||||
* `/lib/domain/libimagnumberstorage/src/error.rs`
|
||||
|
||||
where `store.rs` contains a trait `NumberStorage` and `entry.rs` contains a
|
||||
trait `NumberEntry`.
|
||||
`error.rs` contains the invocation of the `error_chain!{}` macro.
|
||||
Error types from `libimagstore` and others are linked in.
|
||||
|
Loading…
Reference in a new issue