#[derive(Clone, Debug, Default, PartialEq)]
#[repr(C)]
pub enum OrchestratorStatus {
#[default]
Disconnected = 0,
Connecting,
Connected,
WaitingForToken,
WaitingForEmailValidation,
RetrievingSpace,
RetrievingProject,
}
pub mod rust {
pub use crate::api::state::OrchestratorStatus;
use ockam_api::cloud::email_address::EmailAddress;
use std::cmp::Ordering;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Invitee {
pub name: Option<String>,
pub email: EmailAddress,
}
impl Ord for Invitee {
fn cmp(&self, other: &Self) -> Ordering {
self.email.cmp(&other.email)
}
}
impl PartialOrd for Invitee {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Invitation {
pub id: String,
pub service_name: String,
pub service_scheme: Option<String>,
pub accepting: bool,
pub accepted: bool,
pub ignoring: bool,
}
impl Ord for Invitation {
fn cmp(&self, other: &Self) -> Ordering {
self.id.cmp(&other.id)
}
}
impl PartialOrd for Invitation {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
#[derive(Default, Clone, Debug, Eq, PartialEq)]
pub struct LocalService {
pub name: String,
pub address: String,
pub port: u16,
pub scheme: Option<String>,
pub shared_with: Vec<Invitee>,
pub available: bool,
}
impl Ord for LocalService {
fn cmp(&self, other: &Self) -> Ordering {
self.name.cmp(&other.name)
}
}
impl PartialOrd for LocalService {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
#[derive(Default, Clone, Debug, Eq, PartialEq)]
pub struct Service {
pub id: String,
pub source_name: String,
pub address: Option<String>,
pub port: Option<u16>,
pub scheme: Option<String>,
pub available: bool,
pub enabled: bool,
}
impl Ord for Service {
fn cmp(&self, other: &Self) -> Ordering {
self.id.cmp(&other.id)
}
}
impl PartialOrd for Service {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ServiceGroup {
pub email: EmailAddress,
pub name: Option<String>,
pub image_url: Option<String>,
pub invitations: Vec<Invitation>,
pub incoming_services: Vec<Service>,
}
impl Ord for ServiceGroup {
fn cmp(&self, other: &Self) -> Ordering {
self.email.cmp(&other.email)
}
}
impl PartialOrd for ServiceGroup {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct ApplicationState {
pub enrolled: bool,
pub loaded: bool,
pub orchestrator_status: OrchestratorStatus,
pub enrollment_name: Option<String>,
pub enrollment_email: Option<EmailAddress>,
pub enrollment_image: Option<String>,
pub enrollment_github_user: Option<String>,
pub local_services: Vec<LocalService>,
pub groups: Vec<ServiceGroup>,
pub sent_invitations: Vec<Invitee>,
}
#[derive(Clone)]
pub struct ApplicationStateCallback(
unsafe extern "C" fn(state: super::c::ApplicationState) -> (),
);
impl ApplicationStateCallback {
pub fn new(
callback: unsafe extern "C" fn(state: super::c::ApplicationState) -> (),
) -> Self {
Self(callback)
}
pub fn call(&self, state: ApplicationState) {
unsafe {
(self.0)(super::convert_application_state_to_c(state));
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct RuntimeInformation {
pub version: String,
pub commit: String,
pub home: Option<String>,
pub controller_addr: Option<String>,
pub controller_identity: Option<String>,
}
}
pub mod c {
use crate::api::state::OrchestratorStatus;
use std::ffi::c_char;
#[repr(C)]
pub struct Invitee {
pub(super) name: *const c_char,
pub(super) email: *const c_char,
}
#[repr(C)]
pub struct Invitation {
pub(super) id: *const c_char,
pub(super) service_name: *const c_char,
pub(super) service_scheme: *const c_char,
pub(super) accepting: u8,
pub(super) accepted: u8,
pub(super) ignoring: u8,
}
#[repr(C)]
pub struct LocalService {
pub(super) name: *const c_char,
pub(super) address: *const c_char,
pub(super) port: u16,
pub(super) scheme: *const c_char,
pub(super) shared_with: *const *const Invitee,
pub(super) available: u8,
}
#[repr(C)]
pub struct Service {
pub(super) id: *const c_char,
pub(super) source_name: *const c_char,
pub(super) address: *const c_char,
pub(super) port: u16,
pub(super) scheme: *const c_char,
pub(super) available: u8,
pub(super) enabled: u8,
}
#[repr(C)]
pub struct ServiceGroup {
pub(super) email: *const c_char,
pub(super) name: *const c_char,
pub(super) image_url: *const c_char,
pub(super) invitations: *const *const Invitation,
pub(super) incoming_services: *const *const Service,
}
#[repr(C)]
pub struct ApplicationState {
pub(super) enrolled: u8,
pub(super) loaded: u8,
pub(super) orchestrator_status: OrchestratorStatus,
pub(super) enrollment_name: *const c_char,
pub(super) enrollment_email: *const c_char,
pub(super) enrollment_image: *const c_char,
pub(super) enrollment_github_user: *const c_char,
pub(super) local_services: *const *const LocalService,
pub(super) groups: *const *const ServiceGroup,
pub(super) sent_invitations: *const *const Invitee,
}
#[repr(C)]
pub struct RuntimeInformation {
pub(super) version: *const c_char,
pub(super) commit: *const c_char,
pub(super) home: *const c_char,
pub(super) controller_addr: *const c_char,
pub(super) controller_identity: *const c_char,
}
}
use crate::api::{append_c_terminator, free_c_string, to_c_string, to_optional_c_string};
use std::ffi::c_char;
fn invitee_to_c(invitee: rust::Invitee) -> *const c::Invitee {
let invitee_c = c::Invitee {
name: to_optional_c_string(invitee.name),
email: to_c_string(invitee.email.to_string()),
};
Box::into_raw(Box::new(invitee_c))
}
fn invite_to_c(invite: rust::Invitation) -> *const c::Invitation {
let invite_c = c::Invitation {
id: to_c_string(invite.id),
service_name: to_c_string(invite.service_name),
service_scheme: to_optional_c_string(invite.service_scheme),
accepting: invite.accepting as u8,
accepted: invite.accepted as u8,
ignoring: invite.ignoring as u8,
};
Box::into_raw(Box::new(invite_c))
}
fn local_service_to_c(local_service: rust::LocalService) -> *const c::LocalService {
let local_service_c = c::LocalService {
name: to_c_string(local_service.name),
address: to_c_string(local_service.address),
port: local_service.port,
scheme: to_optional_c_string(local_service.scheme),
shared_with: append_c_terminator(
local_service
.shared_with
.into_iter()
.map(invitee_to_c)
.collect::<Vec<_>>(),
),
available: local_service.available as u8,
};
Box::into_raw(Box::new(local_service_c))
}
fn service_to_c(service: rust::Service) -> *const c::Service {
let service_c = c::Service {
id: to_c_string(service.id),
source_name: to_c_string(service.source_name),
address: to_optional_c_string(service.address),
port: service.port.unwrap_or(0),
scheme: to_optional_c_string(service.scheme),
available: service.available as u8,
enabled: service.enabled as u8,
};
Box::into_raw(Box::new(service_c))
}
fn group_to_c(group: rust::ServiceGroup) -> *const c::ServiceGroup {
let group_c = c::ServiceGroup {
name: to_optional_c_string(group.name),
email: to_c_string(group.email.to_string()),
image_url: to_optional_c_string(group.image_url),
invitations: append_c_terminator(
group
.invitations
.into_iter()
.map(invite_to_c)
.collect::<Vec<_>>(),
),
incoming_services: append_c_terminator(
group
.incoming_services
.into_iter()
.map(service_to_c)
.collect::<Vec<_>>(),
),
};
Box::into_raw(Box::new(group_c))
}
pub(crate) fn convert_application_state_to_c(state: rust::ApplicationState) -> c::ApplicationState {
c::ApplicationState {
enrolled: state.enrolled as u8,
loaded: state.loaded as u8,
orchestrator_status: state.orchestrator_status,
enrollment_name: to_optional_c_string(state.enrollment_name),
enrollment_email: to_optional_c_string(state.enrollment_email.map(|e| e.to_string())),
enrollment_image: to_optional_c_string(state.enrollment_image),
enrollment_github_user: to_optional_c_string(state.enrollment_github_user),
local_services: append_c_terminator(
state
.local_services
.into_iter()
.map(local_service_to_c)
.collect::<Vec<_>>(),
),
groups: append_c_terminator(state.groups.into_iter().map(group_to_c).collect::<Vec<_>>()),
sent_invitations: append_c_terminator(
state
.sent_invitations
.into_iter()
.map(invitee_to_c)
.collect::<Vec<_>>(),
),
}
}
pub(crate) fn convert_runtime_information_to_c(
info: rust::RuntimeInformation,
) -> c::RuntimeInformation {
c::RuntimeInformation {
version: to_c_string(info.version),
commit: to_c_string(info.commit),
home: to_optional_c_string(info.home),
controller_addr: to_optional_c_string(info.controller_addr),
controller_identity: to_optional_c_string(info.controller_identity),
}
}
pub(crate) fn free_runtime_information_free(info: c::RuntimeInformation) {
unsafe {
free_c_string(info.version as *const c_char);
free_c_string(info.commit as *const c_char);
free_c_string(info.home as *const c_char);
free_c_string(info.controller_addr as *const c_char);
free_c_string(info.controller_identity as *const c_char);
}
}