Skip to content

Commit

Permalink
Add FFI document interface base
Browse files Browse the repository at this point in the history
ChillFish8 committed Nov 22, 2024

Unverified

The committer email address is not verified.
1 parent 2dc1df8 commit 1dbc301
Showing 8 changed files with 137 additions and 0 deletions.
1 change: 1 addition & 0 deletions .idea/lnx.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions lnx-compile/shared/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions lnx-compile/shared/Cargo.toml
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@ members = [
]

[workspace.dependencies]
thiserror = "2"
serde = "1"
serde_derive = "1"
serde_json = "1"
1 change: 1 addition & 0 deletions lnx-compile/shared/lnx-ffi/Cargo.toml
Original file line number Diff line number Diff line change
@@ -5,3 +5,4 @@ edition = "2021"

[dependencies]
rkyv = { workspace = true }
thiserror = { workspace = true }
36 changes: 36 additions & 0 deletions lnx-compile/shared/lnx-ffi/src/document.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use crate::error::DocumentError;
use crate::format::Format;

#[macro_export]
/// A magic macro for exporting interactions between the
/// compiled library and main process.
///
/// This is done on the base implementation of a type implementing
/// [Document].
macro_rules! extern_magic {
() => {};
}
/// A common document interface between the main lnx process and the compiled
/// libraries.
///
///
pub trait Document: Sized {
/// The type the document uses as its [rkyv::Archived] view.
type ArchivedView;

/// Load a set of [Document] instances from the given buffer with the given format.
fn load_owned_from_buffer(buffer: &[u8], kind: Format) -> Result<Vec<Self>, DocumentError>;

/// Serializes the document to a rkyv buffer.
fn serialize(&self) -> Result<(), DocumentError>;

/// Gets a reference to the archived document.
fn access<'a>(buffer: &'a [u8]) -> Result<&'a Self::ArchivedView, DocumentError>;
}

pub trait ArchivedDocument {
/// Serialize the document to JSON string.
fn serialize_to_json(&self);
/// Serialize the document to MSGPACK binary data.
fn serialize_to_msgpack(&self);
}
61 changes: 61 additions & 0 deletions lnx-compile/shared/lnx-ffi/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
use std::ffi::CString;
use std::fmt::{Debug, Display, Formatter};

#[repr(C)]
#[derive(Debug, thiserror::Error)]
#[error("{kind:?}: {message}")]
/// An error that can occur from the document FFI api.
pub struct DocumentError {
kind: ErrorKind,
message: AssumedSafeCString,
}


#[repr(C)]
#[derive(Debug)]
/// The kind of error that originated.
pub enum ErrorKind {
/// THe document is malformed.
Malformed,
}


#[repr(transparent)]
/// A wrapper type that internally knows the CString
/// is safely UTF-8. This is just for interop.
struct AssumedSafeCString(CString);

impl AssumedSafeCString {
fn as_str(&self) -> &str {
let inner = self.0.as_bytes();
unsafe { std::str::from_utf8_unchecked(inner) }
}
}

impl Display for AssumedSafeCString {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
<str as Display>::fmt(self.as_str(), f)
}
}

impl Debug for AssumedSafeCString {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
<str as Debug>::fmt(self.as_str(), f)
}
}

impl From<&str> for AssumedSafeCString {
fn from(value: &str) -> Self {
let inner = CString::new(value)
.expect("String should not contain null terminator within it");
Self(inner)
}
}

impl From<String> for AssumedSafeCString {
fn from(value: String) -> Self {
let inner = CString::new(value)
.expect("String should not contain null terminator within it");
Self(inner)
}
}
13 changes: 13 additions & 0 deletions lnx-compile/shared/lnx-ffi/src/format.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

#[repr(C)]
/// A signal that indicates what format a buffer is in.
pub enum Format {
/// The buffer is in the JSON format as a single object.
Json,
/// The buffer is in the NDJSON format which contains potentially
/// multiple documents.
Ndjson,
/// The buffer is in the MSGPACK format which contains potentially
/// multiple documents _or_ a single object map.
Msgpack,
}
3 changes: 3 additions & 0 deletions lnx-compile/shared/lnx-ffi/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mod document;
mod format;
mod error;

0 comments on commit 1dbc301

Please sign in to comment.