/* This file is part of DarkFi (https://dark.fi)
*
* Copyright (C) 2020-2026 Dyne.org foundation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
use crate::error::{Error, Result};
use darkfi_serial::{async_trait, Encodable, FutAsyncWriteExt, SerialDecodable, SerialEncodable};
use std::{
io::Write,
sync::{Arc, Mutex as SyncMutex, Weak},
};
use crate::{
expr::SExprCode,
pubsub::{Publisher, PublisherPtr, Subscription},
scene::{SceneNodeId, SceneNodeWeak},
};
mod guard;
pub use guard::{BatchGuardId, BatchGuardPtr, PropertyAtomicGuard};
mod wrap;
pub use wrap::{
PropertyBool, PropertyColor, PropertyDimension, PropertyFloat32, PropertyRect, PropertyStr,
PropertyUint32,
};
#[derive(Debug, Copy, Clone, PartialEq, SerialEncodable, SerialDecodable)]
#[repr(u8)]
pub enum PropertyType {
Null = 0,
Bool = 1,
Uint32 = 2,
Float32 = 3,
Str = 4,
Enum = 5,
SceneNodeId = 7,
SExpr = 8,
}
impl PropertyType {
fn default_value(&self) -> PropertyValue {
match self {
Self::Null => PropertyValue::Null,
Self::Bool => PropertyValue::Bool(false),
Self::Uint32 => PropertyValue::Uint32(0),
Self::Float32 => PropertyValue::Float32(0.),
Self::Str => PropertyValue::Str(String::new()),
Self::Enum => PropertyValue::Enum(String::new()),
Self::SceneNodeId => PropertyValue::SceneNodeId(0),
Self::SExpr => PropertyValue::SExpr(Arc::new(vec![])),
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, SerialEncodable, SerialDecodable)]
#[repr(u8)]
pub enum PropertySubType {
Null = 0,
Color = 1,
// Size of something in pixels
Pixel = 2,
ResourceId = 3,
Locale = 4,
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Role {
User = 0,
App = 1,
Internal = 2,
Ignored = 3,
}
#[derive(Debug, Clone, PartialEq)]
pub enum PropertyValue {
Unset,
Null,
Bool(bool),
Uint32(u32),
Float32(f32),
Str(String),
Enum(String),
SceneNodeId(SceneNodeId),
SExpr(Arc),
}
impl PropertyValue {
fn as_type(&self) -> PropertyType {
match self {
Self::Unset => todo!("not sure"),
Self::Null => PropertyType::Null,
Self::Bool(_) => PropertyType::Bool,
Self::Uint32(_) => PropertyType::Uint32,
Self::Float32(_) => PropertyType::Float32,
Self::Str(_) => PropertyType::Str,
Self::Enum(_) => PropertyType::Enum,
Self::SceneNodeId(_) => PropertyType::SceneNodeId,
Self::SExpr(_) => PropertyType::SExpr,
}
}
pub fn is_unset(&self) -> bool {
match self {
Self::Unset => true,
_ => false,
}
}
pub fn is_null(&self) -> bool {
match self {
Self::Null => true,
_ => false,
}
}
pub fn is_expr(&self) -> bool {
match self {
Self::SExpr(_) => true,
_ => false,
}
}
pub fn as_bool(&self) -> Result {
match self {
Self::Bool(v) => Ok(*v),
_ => Err(Error::PropertyWrongType),
}
}
pub fn as_u32(&self) -> Result {
match self {
Self::Uint32(v) => Ok(*v),
_ => Err(Error::PropertyWrongType),
}
}
pub fn as_f32(&self) -> Result {
match self {
Self::Float32(v) => Ok(*v),
_ => Err(Error::PropertyWrongType),
}
}
pub fn as_str(&self) -> Result {
match self {
Self::Str(v) => Ok(v.clone()),
_ => Err(Error::PropertyWrongType),
}
}
pub fn as_enum(&self) -> Result {
match self {
Self::Enum(v) => Ok(v.clone()),
_ => Err(Error::PropertyWrongType),
}
}
pub fn as_node_id(&self) -> Result {
match self {
Self::SceneNodeId(v) => Ok(*v),
_ => Err(Error::PropertyWrongType),
}
}
pub fn as_sexpr(&self) -> Result> {
match self {
Self::SExpr(v) => Ok(v.clone()),
_ => Err(Error::PropertyWrongType),
}
}
}
impl Encodable for PropertyValue {
fn encode(&self, s: &mut S) -> std::result::Result {
match self {
Self::Unset | Self::Null => {
// do nothing
Ok(0)
}
Self::Bool(v) => v.encode(s),
Self::Uint32(v) => v.encode(s),
Self::Float32(v) => v.encode(s),
Self::Str(v) => v.encode(s),
Self::Enum(v) => v.encode(s),
Self::SceneNodeId(v) => v.encode(s),
Self::SExpr(v) => v.encode(s),
}
}
}
#[derive(Debug, Clone)]
pub enum ModifyAction {
Clear,
Set(usize),
SetCache(Vec),
Push(usize),
}
type ModifyPublisher = PublisherPtr<(Role, ModifyAction, BatchGuardPtr)>;
pub type PropertyPtr = Arc;
pub type PropertyWeak = Weak;
#[derive(Debug, Clone)]
pub struct PropertyDepend {
pub prop: PropertyWeak,
pub i: usize,
pub local_name: String,
}
pub struct Property {
pub name: String,
pub node: SyncMutex