some more restorations

This commit is contained in:
Sebastian Moser
2026-10-23 11:29:39 +02:00
parent 48f7ee2e35
commit 9e5ceaf0f9
14 changed files with 1170 additions and 9179 deletions

0
core/src/c_api.rs Normal file
View File

367
core/src/error.rs Normal file
View File

@@ -0,0 +1,367 @@
use colored::Colorize;
#[cfg(feature = "target-js")]
use wasm_bindgen::JsValue;
use core::result::Result;
use core::result::Result::Ok;
use std::collections::HashMap;
use std::fmt::format;
use std::fmt::Debug;
use std::fmt::Display;
use std::io;
use std::string::FromUtf8Error;
use tracing::{debug, error, info, trace, warn};
//use crate::proto::MizeMessage;
#[macro_export]
macro_rules! mize_err {
($($arg:tt)*) => { MizeError::new().msg(format!( $($arg)*)) };
}
pub type MizeResult<T> = Result<T, MizeError>;
pub trait MizeResultTrait<T> {
fn critical(self) -> T;
fn as_std(self) -> Result<T, MizeErrorWhichImplementsError>;
}
pub trait IntoMizeResult<T, S> {
fn mres(self) -> MizeResult<T>;
fn mres_msg(self, msg: S) -> MizeResult<T>
where
S: std::fmt::Display;
}
#[derive(Debug, Clone)]
pub struct MizeError {
pub category: Vec<String>,
pub code: u32,
pub messages: Vec<String>,
//pub caused_by_msg: Option<CausedByMessage>,
pub code_location: Option<MizeCodeLocation>,
pub backtrace: String,
}
/*
#[derive(Debug, Clone)]
pub struct CausedByMessage {
// peer: &Connection, // TODO: add later
msg: Box<MizeMessage>,
}
*/
#[derive(Debug, Clone)]
pub struct MizeCodeLocation {
file: String,
line: u32,
column: u32,
}
impl Display for MizeCodeLocation {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"file: {} line: {} column: {}",
self.file, self.line, self.column
)
}
}
impl From<&std::panic::Location<'_>> for MizeCodeLocation {
fn from(panic_location: &std::panic::Location) -> MizeCodeLocation {
let file = panic_location.file().to_string();
let line = panic_location.line();
let column = panic_location.column();
MizeCodeLocation { file, line, column }
}
}
impl MizeError {
#[track_caller]
pub fn code(code: u32) -> MizeError {
let caller_location = std::panic::Location::caller();
get_error_by_code(code, caller_location)
}
pub fn set_code(mut self, code: u32) -> MizeError {
self.code = code;
return self;
}
#[track_caller]
pub fn new() -> MizeError {
let caller_location = std::panic::Location::caller();
return MizeError {
category: Vec::new(),
code: 0,
messages: Vec::new(),
code_location: Some(caller_location.into()),
backtrace: format!("{}", std::backtrace::Backtrace::capture()),
};
}
pub fn msg<E>(mut self, msg: E) -> MizeError
where
E: std::fmt::Display,
{
self.messages.push(format!("{}", msg));
return self;
}
pub fn category<T>(mut self, category: T) -> MizeError
where
T: Into<String>,
{
self.category.push(category.into());
return self;
}
fn send(self) -> MizeError {
self
}
fn add_to_err_item(self) -> MizeError {
self
}
pub fn log(self) -> MizeError {
println!("[ {} ] MizeError encountered!", "ERROR".red());
if let Some(ref location) = self.code_location {
println!("[ {} ] {}", "LOCATION".yellow(), location);
};
println!("[ {} ] {}", "BACKTRACE".yellow(), self.backtrace);
for msg in &self.messages {
println!("[ {} ] {}", "MSG".yellow(), msg);
}
self
}
pub fn handle(self) -> MizeError {
return self.send().add_to_err_item().log();
}
pub fn critical(self) {
let mut msg_iter = self.messages.iter();
match msg_iter.next() {
None => {
error!("{} MizeError with code: {}", "CRITICAL".red(), self.code);
}
Some(msg) => {
error!(
"{} MizeError with code: {} - {}",
"CRITICAL".red(),
self.code,
msg
);
}
}
for msg in msg_iter {
error!("{} {}", "MSG".red(), msg)
}
if let Some(location) = self.code_location {
error!("{} {}", "LOCATION".red(), location)
}
panic!();
}
pub fn location(mut self, location: MizeCodeLocation) -> MizeError {
self.code_location = Some(location);
self
}
}
/*
pub trait MizeResultExtension<T> {
fn extra_msg<E>(self, msg: E) -> Result<T, MizeError>
where E: std::fmt::Display
;
fn handle(self) -> Result<T, MizeError>;
fn is_critical(self) -> T;
}
impl<T> MizeResultExtension<T> for Result<T, MizeError> {
fn msg<E>(mut self, msg: E) -> Result<T, MizeError>
where E: std::fmt::Display
{
match self {
Err(ref mut e) => {
e.msg.push(format!("{}", msg));
return self;
},
Ok(something) => Ok(something),
}
}
fn handle(self) -> Result<T, MizeError> {
match self {
Err(e) => {
Err(e.send().add_to_err_item().write_to_stderr())
},
Ok(something) => Ok(something)
}
}
fn is_critical(self) -> T {
self.expect("Aborting because of a critical Error")
}
}
*/
/*
impl From<FromUtf8Error> for MizeError {
#[track_caller]
fn from(utf_err: FromUtf8Error) -> MizeError{
let caller_location = std::panic::Location::caller();
let mut err = MizeError::code(109).msg(format!("From std::string::FromUtf8Error: {}", utf_err));
err.code_location = Some(caller_location.into());
return err;
}
}
*/
impl<T: Display> From<T> for MizeError {
#[track_caller]
fn from(value: T) -> Self {
let caller_location = std::panic::Location::caller();
MizeError::new()
.msg(format!(
"From {}: {}",
std::any::type_name_of_val(&value),
value
))
.location(caller_location.into())
}
}
impl<T> MizeResultTrait<T> for MizeResult<T> {
fn critical(self) -> T {
match self {
Ok(val) => val,
Err(err) => {
err.critical();
unreachable!()
}
}
}
fn as_std(self) -> Result<T, MizeErrorWhichImplementsError> {
match self {
Ok(val) => Ok(val),
Err(err) => Err(MizeErrorWhichImplementsError { inner: err }),
}
}
}
impl<T, E, S> IntoMizeResult<T, S> for Result<T, E>
where
E: std::fmt::Display,
{
#[track_caller]
fn mres(self) -> MizeResult<T> {
let caller_location = std::panic::Location::caller();
match self {
Ok(val) => MizeResult::Ok(val),
Err(err) => MizeResult::Err(MizeError::new().category("misc").msg(format!(
"From {}: {}",
std::any::type_name_of_val(&err),
err
))),
}
}
#[track_caller]
fn mres_msg(self, msg: S) -> MizeResult<T>
where
S: std::fmt::Display,
{
let caller_location = std::panic::Location::caller();
match self {
Ok(val) => MizeResult::Ok(val),
Err(err) => MizeResult::Err(
MizeError::new()
.category("misc")
.msg(format!("{}", msg))
.msg(format!(
"From {}: {}",
std::any::type_name_of_val(&err),
err
)),
),
}
}
}
fn get_error_by_code(code: u32, caller_location: &std::panic::Location) -> MizeError {
let err = MizeError {
category: Vec::new(),
code: 0,
messages: Vec::new(),
code_location: Some(caller_location.into()),
backtrace: format!("{}", std::backtrace::Backtrace::capture()),
};
match code {
109 => err
.set_code(109)
.category("decoding")
.msg("conversion from utf8 failed"),
108 => err
.set_code(108)
.category("decoding")
.msg("serde deserialisation failed"),
_ => err,
}
}
#[derive(Debug, Clone)]
pub struct MizeErrorWhichImplementsError {
inner: MizeError,
}
impl Display for MizeErrorWhichImplementsError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "MizeError envountered!");
if let Some(ref location) = self.inner.code_location {
write!(f, "[ {} ] {}", "LOCATION".yellow(), location);
};
write!(f, "[ {} ] {}", "BACKTRACE".yellow(), self.inner.backtrace);
for msg in &self.inner.messages {
write!(f, "[ {} ] {}", "MSG".yellow(), msg);
}
Ok(())
}
}
impl From<MizeError> for MizeErrorWhichImplementsError {
fn from(value: MizeError) -> Self {
MizeErrorWhichImplementsError { inner: value }
}
}
impl std::error::Error for MizeErrorWhichImplementsError {}
// i hate rust sometimes.
// why can't i impl IntoMizeResult for any type. and the extra concrete impl of it for JsValue overrides the more generic one.
#[cfg(feature = "target-js")]
pub trait IntoMizeResultJsValue<T> {
fn mres(self) -> MizeResult<T>;
}
#[cfg(feature = "target-js")]
impl<T> IntoMizeResultJsValue<T> for Result<T, JsValue> {
fn mres(self) -> MizeResult<T> {
match self {
Ok(value) => Ok(value),
Err(err) => Err(mize_err!("From JsValue: {:?}", err)),
}
}
}

172
core/src/lib.rs Normal file
View File

@@ -0,0 +1,172 @@
#![allow(warnings)]
use std::cell::RefCell;
use std::fmt::format;
#[macro_export]
macro_rules! out {
($($arg:tt)*) => {
// format_args! handles string interpolation safely at compile time
if let Err(e) = $crate::write_to_mize_stdout(format_args!($($arg)*)) {
// Choose your error handling behavior here (panic, print to stderr, or ignore)
eprintln!("out! macro failed to write!!");
}
};
}
pub fn write_to_mize_stdout(args: std::fmt::Arguments) -> MizeResult<()> {
println!("{}", format_args!(args));
Ok(())
}
pub mod prelude {
pub use super::*;
pub use instance::Mize;
pub use error::MizeError;
pub use crate::mize_err;
pub use error::MizeResult;
pub use item::{Item, ItemData, IntoItemData};
pub use config::*;
}
pub use flume;
// the core part has the code that can run on any platform
pub mod config;
pub mod error;
pub mod id;
pub mod instance;
pub mod item;
pub mod memstore;
pub mod proto;
pub mod types;
pub mod c_api;
pub use async_trait::async_trait;
pub use ciborium;
pub use error::MizeError;
pub use error::MizeResult;
pub use instance::Mize;
pub use instance::{
MizePart,
};
pub use mize_macros::*;
use std::path::PathBuf;
// platform specific stuff
pub mod platform {
use crate::{Mize, MizeResult};
#[cfg(feature = "target-js")]
pub mod js;
#[cfg(feature = "target-os")]
pub mod os;
pub fn init(mize: &mut Mize) -> MizeResult<()> {
#[cfg(feature = "target-os")] {
os::os_instance_init(mize)?;
}
#[cfg(feature = "target-js")] {
js::wasm_instance_init(mize)?;
}
Ok(())
}
pub fn load_part(mize: &mut Mize, part_name: &str, path: Option<String>) -> MizeResult<()> {
#[cfg(feature = "target-os")] {
os::load_part(mize, part_name, path)?;
}
Ok(())
}
pub fn fetch_part(mize: &mut Mize, part_name: &str) -> MizeResult<String> {
#[cfg(feature = "target-os")] {
os::fetch_part(mize, part_name)?;
}
Ok("alsdkjf".to_owned())
}
}
////////////////////////////////////// include_native! macro /////////////////////////////////////
// A macro to register methods of a foreign type (like clap::Command) with mize.
// This generates bindings for the type to be stored in the native_values registry.
// Usage 1: New simplified syntax (string name, type path, list of method names)
// ```ignore
// include_native!("Command", clap::Command, [new, arg, subcommand]);
// ```
//
// This expands to:
// ```ignore
// opt("Command")
// .method("new", |args| {
// let this = get_config("Command")?.native_mut::<clap::Command>()?;
// let result = this.new();
// Ok(from_native(result))
// })
// .method("arg", |args| {
// let this = get_config("Command")?.native_mut::<clap::Command>()?;
// let result = this.arg();
// Ok(from_native(result))
// })
// .method("subcommand", |args| {
// let this = get_config("Command")?.native_mut::<clap::Command>()?;
// let result = this.subcommand();
// Ok(from_native(result))
// });
// ```
//
// Usage 2: Traditional syntax (type path, method signatures in braces)
// ```ignore
// include_native!(clap::Command, {
// fn arg(&mut self, arg: clap::Arg) -> &mut clap::Command;
// fn subcommand(&mut self, cmd: clap::Command) -> &mut clap::Command;
// });
// ```
//
// This expands to:
// ```ignore
// opt("clap::Command")
// .method("arg", |args| {
// let arg = args.arr_nth(0)?.native::<clap::Arg>()?;
// let this = get_config("clap::Command")?.native_mut::<clap::Command>()?;
// let result = this.arg(arg);
// Ok(from_native(result))
// })
// .method("subcommand", |args| {
// let cmd = args.arr_nth(0)?.native::<clap::Command>()?;
// let this = get_config("clap::Command")?.native_mut::<clap::Command>()?;
// let result = this.subcommand(cmd);
// Ok(from_native(result))
// });
// ```
#[macro_export]
macro_rules! include_native {
// New simplified syntax: ("name", type_path, [method1, method2, ...])
($name:literal, $type_path:ty, [$($method:ident),* $(,)?]) => {
$crate::config::opt($name)
$(
.method(stringify!($method), |args| {
let this = $crate::c_api::get_global_mize()?
.get_config($name)?
.native_mut::<$type_path>()?;
let result = this.$method();
Ok($crate::item::ItemData::from_native(result)?)
})
)*
};
// Traditional syntax: (type_path, { fn method1(...) -> ...; fn method2(...) -> ...; })
($type_path:ty, { $($methods:tt)* }) => {
$crate::config::opt(stringify!($type_path))
// TODO: parse method signatures and generate appropriate bindings
// For now, this is a placeholder for the traditional syntax
};
}

152
core/src/memstore.rs Normal file
View File

@@ -0,0 +1,152 @@
use ciborium::Value as CborValue;
use colored::Colorize;
use std::collections::binary_heap::Iter;
use std::collections::HashMap;
use std::iter::Map;
use std::sync::{Arc, Mutex};
use tracing::{instrument, trace};
use crate::error::{IntoMizeResult, MizeError, MizeResult};
use crate::id::MizeId;
use crate::instance::store::{IdIter, Store};
use crate::instance::Mize;
use crate::item::get_raw_from_cbor;
use crate::item::{Item, ItemData};
use crate::mize_err;
#[derive(Clone, Debug)]
pub struct MemStore {
inner: Arc<Mutex<MemStoreInner>>,
}
pub type MemStoreId = u64;
#[derive(Debug)]
struct MemStoreInner {
map: HashMap<u64, ItemData>,
next_id: u64,
}
impl Store for MemStore {
fn set(&self, id: MizeId, data: ItemData) -> MizeResult<()> {
let mut inner = self.inner.lock()?;
if let Some(old_data) = inner.map.get(&id_to_u64(id.clone())?) {
//if there is already data there, set at the correct path
let mut old_data = old_data.to_owned();
let path = id.after_store_part();
old_data.set_path(path, data)?;
inner.map.insert(id_to_u64(id)?, old_data);
} else {
// if no data exists for that store_part, just insert
inner.map.insert(id_to_u64(id)?, data);
}
return Ok(());
}
fn get_links(&self, item: Item) -> MizeResult<Vec<MizeId>> {
let inner = self.inner.lock()?;
Ok(Vec::new())
}
fn get_backlinks(&self, item: Item) -> MizeResult<Vec<MizeId>> {
let inner = self.inner.lock()?;
Ok(Vec::new())
}
fn new_id(&self) -> MizeResult<String> {
let mut inner = self.inner.lock()?;
let id_string = format!("{}", inner.next_id);
inner.next_id += 1;
return Ok(id_string);
}
#[instrument(name="fn.MemStore::get_value_raw" skip(self))]
fn get_value_raw(&self, id: MizeId) -> MizeResult<Vec<u8>> {
trace!("[ {} ] id: {:?}", "ARG".yellow(), id);
let inner = self.inner.lock()?;
let cbor_val = inner
.map
.get(&id_to_u64(id.clone())?)
.ok_or(MizeError::new().msg(format!(
"Item with store_part: {}, id: {} does not exist in MemStore",
id_to_u64(id.clone())?,
id
)))?;
let path = id.path();
let mut id_iter = path.iter();
id_iter.next();
let id_without_first = id_iter.collect();
Ok(get_raw_from_cbor(&cbor_val.0, id_without_first)?.to_owned())
}
fn get_value_data_full(&self, id: MizeId) -> MizeResult<ItemData> {
let inner = self.inner.lock()?;
let data = match inner.map.get(&id_to_u64(id.clone())?) {
Some(val) => val.to_owned(),
None => ItemData::new(),
};
let new_path = id.after_store_part();
let ret_data = data.get_path(new_path)?;
return Ok(ret_data);
}
fn id_iter(&self) -> MizeResult<IdIter> {
IdIter::new(Box::new(self.to_owned()))
}
fn next_id(&self, prev_id_str: &str) -> MizeResult<Option<String>> {
let inner = self.inner.lock()?;
let mut id = str_to_u64(prev_id_str)?;
loop {
id += 1;
if id > inner.next_id {
return Ok(None);
}
if inner.map.contains_key(&id) {
println!("returning: {}", id);
return Ok(Some(format!("{}", id)));
} else {
// try id +1
continue;
}
}
}
fn first_id(&self) -> MizeResult<String> {
Ok("0".to_owned())
}
}
impl MemStore {
pub fn new() -> MemStore {
let inner = MemStoreInner {
map: HashMap::new(),
next_id: 0,
};
return MemStore {
inner: Arc::new(Mutex::new(inner)),
};
}
}
fn id_to_u64(id: MizeId) -> MizeResult<u64> {
str_to_u64(id.store_part())
}
fn str_to_u64(id_str: &str) -> MizeResult<u64> {
id_str.parse().mres_msg(format!(
"Could not parse the store_part of mizeid {} into a u64 for the MemStore",
id_str
))
}

View File

@@ -303,7 +303,7 @@ fn get_part_path(mize: &mut Mize, part_name: &str, _path: Option<String>) -> Miz
}
pub fn load_part(mize: &mut Mize, part_name: &str, path: Option<String>) -> MizeResult<()> {
let part_path = get_part_path(mize, part_name, path)?;
let part_path = get_part_path(mize, part_name, path)?;
let lib = unsafe { libloading::Library::new(part_path)? };

434
core/src/proto/mod.rs Normal file
View File

@@ -0,0 +1,434 @@
use core::fmt;
use serde::Serialize;
use std::io;
use ciborium::{value::Integer, Value as CborValue};
use crate::{
error::{IntoMizeResult, MizeError, MizeResult},
id::MizeId,
instance::{self, connection::Connection, Mize},
item::{IntoItemData, ItemData},
};
#[derive(Clone)]
pub struct MizeMessage {
value: CborValue,
pub conn_id: u64,
}
impl MizeMessage {
pub fn bytes(&self) -> Vec<u8> {
let mut writer = Vec::new();
ciborium::into_writer(&self.value, &mut writer).unwrap();
writer
}
pub fn into_writer(&self, writer: &mut impl io::Write) -> MizeResult<()> {
Ok(ciborium::into_writer(&self.value, writer)?)
}
}
// msg items
static MSG_CMD: u16 = 1;
static MSG_ID: u16 = 2;
static MSG_DATA: u16 = 3;
// cmds
static CMD_GET: u16 = 1;
static CMD_UPDATE: u16 = 2;
static CMD_GIVE: u16 = 3;
static CMD_CREATE: u16 = 4;
static CMD_CREATE_REPLY: u16 = 5;
static CMD_UPDATE_REQUEST: u16 = 6;
static CMD_GET_SUB: u16 = 7;
static CMD_SUB: u16 = 8;
#[derive(Debug)]
pub enum MessageCmd {
Get,
Update,
Give,
Create,
CreateReply,
UpdateRequest,
GetSub,
Sub,
Custom(ItemData),
}
impl MizeMessage {
pub fn new(value: CborValue, conn_id: u64) -> MizeMessage {
MizeMessage { value, conn_id }
}
pub fn new_custom<T: IntoItemData, U: IntoItemData>(
custom_cmd: T,
value: U,
conn_id: u64,
) -> MizeMessage {
let value = value.into_item_data();
let custom_cmd = custom_cmd.into_item_data();
let cmd = (CborValue::Integer(MSG_CMD.into()), custom_cmd.0);
let data = (CborValue::Integer(MSG_DATA.into()), value.cbor().to_owned());
let msg_value = CborValue::Map(vec![cmd, data]);
MizeMessage {
value: msg_value,
conn_id,
}
}
pub fn new_get(id: MizeId, conn_id: u64) -> MizeMessage {
let id_path = id
.path()
.into_iter()
.map(|string| CborValue::Text(string.to_owned()))
.collect();
let cmd = (
CborValue::Integer(MSG_CMD.into()),
CborValue::Integer(CMD_GET.into()),
);
let id = (CborValue::Integer(MSG_ID.into()), CborValue::Array(id_path));
let value = CborValue::Map(vec![cmd, id]);
MizeMessage::new(value, conn_id)
}
pub fn new_get_sub(id: MizeId, conn_id: u64) -> MizeMessage {
let id_path = id
.path()
.into_iter()
.map(|string| CborValue::Text(string.to_owned()))
.collect();
let cmd = (
CborValue::Integer(MSG_CMD.into()),
CborValue::Integer(CMD_GET_SUB.into()),
);
let id = (CborValue::Integer(MSG_ID.into()), CborValue::Array(id_path));
let value = CborValue::Map(vec![cmd, id]);
MizeMessage::new(value, conn_id)
}
pub fn new_sub(id: MizeId, conn_id: u64) -> MizeMessage {
let id_path = id
.path()
.into_iter()
.map(|string| CborValue::Text(string.to_owned()))
.collect();
let cmd = (
CborValue::Integer(MSG_CMD.into()),
CborValue::Integer(CMD_SUB.into()),
);
let id = (CborValue::Integer(MSG_ID.into()), CborValue::Array(id_path));
let value = CborValue::Map(vec![cmd, id]);
MizeMessage::new(value, conn_id)
}
pub fn new_create(conn_id: u64) -> MizeMessage {
let cmd = (
CborValue::Integer(MSG_CMD.into()),
CborValue::Integer(CMD_CREATE.into()),
);
let value = CborValue::Map(vec![cmd]);
MizeMessage::new(value, conn_id)
}
pub fn new_create_reply(id: MizeId, conn_id: u64) -> MizeMessage {
let id_path = id
.path()
.into_iter()
.map(|string| CborValue::Text(string.to_owned()))
.collect();
let cmd = (
CborValue::Integer(MSG_CMD.into()),
CborValue::Integer(CMD_CREATE_REPLY.into()),
);
let id = (CborValue::Integer(MSG_ID.into()), CborValue::Array(id_path));
let value = CborValue::Map(vec![cmd, id]);
MizeMessage::new(value, conn_id)
}
pub fn new_give(id: MizeId, data: ItemData, conn_id: u64) -> MizeMessage {
let id_path = id
.path()
.into_iter()
.map(|string| CborValue::Text(string.to_owned()))
.collect();
let cmd = (
CborValue::Integer(MSG_CMD.into()),
CborValue::Integer(CMD_GIVE.into()),
);
let id = (CborValue::Integer(MSG_ID.into()), CborValue::Array(id_path));
let data = (CborValue::Integer(MSG_DATA.into()), data.cbor().to_owned());
let value = CborValue::Map(vec![cmd, id, data]);
MizeMessage::new(value, conn_id)
}
pub fn new_update_request(id: MizeId, data: ItemData, conn_id: u64) -> MizeMessage {
let id_path = id
.path()
.into_iter()
.map(|string| CborValue::Text(string.to_owned()))
.collect();
let cmd = (
CborValue::Integer(MSG_CMD.into()),
CborValue::Integer(CMD_UPDATE_REQUEST.into()),
);
let id = (CborValue::Integer(MSG_ID.into()), CborValue::Array(id_path));
let data = (CborValue::Integer(MSG_DATA.into()), data.cbor().to_owned());
let value = CborValue::Map(vec![cmd, id, data]);
MizeMessage::new(value, conn_id)
}
pub fn new_update(id: MizeId, data: ItemData, conn_id: u64) -> MizeMessage {
let id_path = id
.path()
.into_iter()
.map(|string| CborValue::Text(string.to_owned()))
.collect();
let cmd = (
CborValue::Integer(MSG_CMD.into()),
CborValue::Integer(CMD_UPDATE.into()),
);
let id = (CborValue::Integer(MSG_ID.into()), CborValue::Array(id_path));
let data = (CborValue::Integer(MSG_DATA.into()), data.cbor().to_owned());
let value = CborValue::Map(vec![cmd, id, data]);
MizeMessage::new(value, conn_id)
}
pub fn value(self) -> CborValue {
self.value
}
pub fn cmd(&self) -> MizeResult<MessageCmd> {
// return err, if msg is not a map
let msg_as_map = match &self.value {
CborValue::Map(val) => val,
_ => {
return Err(MizeError::new().msg("Message was not a map"));
}
};
//check if in this map there is a cmd, otherwise return err
let val_of_c = {
let mut tmp_val = 0;
for (key, val) in msg_as_map {
if let CborValue::Integer(key_int) = key {
// number one indicates the cmd field
let one: Integer = 1.into();
if key_int == &one {
if let CborValue::Integer(val_int) = val {
tmp_val = val_int.to_owned().into();
} else {
return Ok(MessageCmd::Custom(ItemData(val.to_owned())));
}
}
}
}
if tmp_val == 0 {
return Err(MizeError::new().msg("error getting the cmd value form a msg"));
}
tmp_val
};
// match on value of cmd
let cmd = match val_of_c {
1 => MessageCmd::Get,
2 => MessageCmd::Update,
3 => MessageCmd::Give,
4 => MessageCmd::Create,
5 => MessageCmd::CreateReply,
6 => MessageCmd::UpdateRequest,
7 => MessageCmd::GetSub,
8 => MessageCmd::Sub,
_ => {
return Err(MizeError::new().msg("error cmd of msg was not a valid command"));
}
};
return Ok(cmd);
}
pub fn id_str(&mut self) -> MizeResult<Vec<String>> {
// return err, if msg is not a map
let msg_as_map = match &self.value {
CborValue::Map(val) => val,
_ => {
return Err(MizeError::new().msg("Message was not a map"));
}
};
let vec_value = {
let mut data = &CborValue::Null;
for (key, val) in msg_as_map {
if let CborValue::Integer(key_int) = key {
// number 2 indicates the id field
let two: Integer = 2.into();
if key_int == &two {
data = val;
}
}
}
if data == &CborValue::Null {
return Err(MizeError::new().msg("error getting the data value form a msg"));
}
match data {
CborValue::Array(inner) => inner,
_ => {
return Err(MizeError::new().msg("Id is not a vector"));
}
}
};
let mut vec_string: Vec<String> = Vec::new();
for val in vec_value {
match val {
CborValue::Text(text) => vec_string.push(text.to_owned()),
_ => {
return Err(MizeError::new()
.msg("one in the vec of the id in a msg is not of type Text"));
}
}
}
Ok(vec_string)
}
pub fn id(&mut self, instance: &Mize) -> MizeResult<MizeId> {
let id_str = self.id_str()?;
return instance.new_id(id_str);
}
pub fn data(&mut self) -> MizeResult<ItemData> {
// return err, if msg is not a map
let msg_as_map = match &self.value {
CborValue::Map(val) => val,
_ => {
return Err(MizeError::new().msg("Message was not a map"));
}
};
let data = {
let mut tmp_val = &CborValue::Null;
let mut found = false;
for (key, val) in msg_as_map {
if let CborValue::Integer(key_int) = key {
// number three indicates the data field
let three: Integer = 3.into();
if key_int == &three {
tmp_val = val;
found = true;
}
}
}
if !found {
return Err(MizeError::new().msg("error getting the data value form a msg"));
}
tmp_val
};
return Ok(data.to_owned().into_item_data());
}
}
// thanks to: https://stackoverflow.com/a/61768916
struct DisplayWriter<'a, 'b>(&'a mut fmt::Formatter<'b>);
impl<'a, 'b> io::Write for DisplayWriter<'a, 'b> {
fn write(&mut self, bytes: &[u8]) -> std::result::Result<usize, std::io::Error> {
self.0
.write_str(&String::from_utf8_lossy(bytes))
.map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err))?;
Ok(bytes.len())
}
fn flush(&mut self) -> std::result::Result<(), std::io::Error> {
todo!()
}
}
impl fmt::Display for MizeMessage {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut err = false;
match self.to_owned().cmd() {
Ok(cmd) => {
writeln!(f, "MizeMessage with cmd: {:?}", cmd);
}
Err(e) => {
writeln!(f, "MizeMessage with unparsable cmd");
err = true;
}
}
match self.to_owned().id_str() {
Ok(id) => {
let id_str = id.join("/");
writeln!(f, "\tid: {:?}", id_str);
}
Err(e) => {
writeln!(f, "\t msg has no id");
//err = true;
}
}
match self.to_owned().data() {
Ok(data) => {
let value = data.cbor();
write!(f, "\tdata: ");
let display_writer = DisplayWriter(f);
if let Err(e) = value
.serialize(&mut serde_json::Serializer::pretty(display_writer))
.map_err(|serde_err| std::fmt::Error)
{
writeln!(f, "serialize err: {:?}", e);
err = true;
}
}
Err(e) => {
writeln!(f, "\t msg has no data");
//err = true;
}
}
if err {
write!(f, "Full msg: ");
let display_writer = DisplayWriter(f);
self.value
.serialize(&mut serde_json::Serializer::pretty(display_writer))
.map_err(|serde_err| std::fmt::Error)
.mres_msg("serialize error")
.inspect_err(|e| {
e.clone().log();
});
}
Ok(())
}
}
impl fmt::Debug for MizeMessage {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "\nMizeMessage: ");
let display_writer = DisplayWriter(f);
let value = self.to_owned().value();
value
.serialize(&mut serde_json::Serializer::pretty(display_writer))
.map_err(|serde_err| std::fmt::Error)
}
}

0
core/src/types/mod.rs Normal file
View File