mod.rs 76 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2026 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use crate::error::{Error, Result};
  19. use darkfi_serial::{async_trait, Encodable, FutAsyncWriteExt, SerialDecodable, SerialEncodable};
  20. use std::{
  21. io::Write,
  22. sync::{Arc, Mutex as SyncMutex, Weak},
  23. };
  24. use crate::{
  25. expr::SExprCode,
  26. pubsub::{Publisher, PublisherPtr, Subscription},
  27. scene::{SceneNodeId, SceneNodeWeak},
  28. ui::VectorShape,
  29. };
  30. mod guard;
  31. pub use guard::{BatchGuard, BatchGuardPtr, PropertyAtomicGuard};
  32. mod wrap;
  33. pub use wrap::{
  34. eval_f32_multi, PropertyBool, PropertyColor, PropertyDimension, PropertyEnum, PropertyFloat32,
  35. PropertyRect, PropertyShape, PropertyStr, PropertyUint32,
  36. };
  37. #[derive(Debug, Copy, Clone, PartialEq, SerialEncodable, SerialDecodable)]
  38. #[repr(u8)]
  39. pub enum PropertyType {
  40. Null = 0,
  41. Bool = 1,
  42. Uint32 = 2,
  43. Float32 = 3,
  44. Str = 4,
  45. Enum = 5,
  46. SceneNodeId = 7,
  47. SExpr = 8,
  48. VectorShape = 9,
  49. }
  50. impl PropertyType {
  51. fn default_value(&self) -> PropertyValue {
  52. match self {
  53. Self::Null => PropertyValue::Null,
  54. Self::Bool => PropertyValue::Bool(false),
  55. Self::Uint32 => PropertyValue::Uint32(0),
  56. Self::Float32 => PropertyValue::Float32(0.),
  57. Self::Str => PropertyValue::Str(String::new()),
  58. Self::Enum => PropertyValue::Enum(String::new()),
  59. Self::SceneNodeId => PropertyValue::SceneNodeId(0),
  60. Self::SExpr => PropertyValue::SExpr(Arc::new(vec![])),
  61. Self::VectorShape => PropertyValue::VectorShape(Arc::new(VectorShape::new())),
  62. }
  63. }
  64. }
  65. #[derive(Debug, Copy, Clone, PartialEq, SerialEncodable, SerialDecodable)]
  66. #[repr(u8)]
  67. pub enum PropertySubType {
  68. Null = 0,
  69. Color = 1,
  70. // Size of something in pixels
  71. Pixel = 2,
  72. ResourceId = 3,
  73. Locale = 4,
  74. Flag = 5,
  75. }
  76. /// Acting role on a property mutation. Doubles as a bitmask for
  77. /// `PropertyPermission` read/write masks, so it is a hand-rolled bitflag
  78. /// set over `u8` (kept dependency-free on purpose).
  79. #[derive(Debug, Copy, Clone, PartialEq, Eq)]
  80. pub struct Role(u8);
  81. impl Role {
  82. // Constants keep CamelCase names on purpose: they are used as
  83. // `Role::App` etc. at hundreds of call sites, mimicking the old
  84. // enum-variant ergonomics.
  85. #![allow(non_upper_case_globals)]
  86. /// End-user action (UI input, settings)
  87. pub const User: Role = Role(1 << 0);
  88. /// Application/schema logic
  89. pub const App: Role = Role(1 << 1);
  90. /// Widget-internal writes (draw-pass evals, runtime-computed state)
  91. pub const Internal: Role = Role(1 << 2);
  92. /// Marker role: "don't notify", rarely part of masks
  93. pub const Ignored: Role = Role(1 << 3);
  94. /// Theme engine writes (stamped by `ThemeCtx` setters)
  95. pub const Theme: Role = Role(1 << 4);
  96. /// The empty mask
  97. pub const NONE: Role = Role(0);
  98. /// All roles
  99. pub const ALL: Role = Role(0b1_1111);
  100. /// True when every bit of `other` is also set in `self`.
  101. pub fn contains(self, other: Role) -> bool {
  102. other.0 & self.0 == other.0
  103. }
  104. /// True when `self` and `other` share at least one bit.
  105. pub fn intersects(self, other: Role) -> bool {
  106. self.0 & other.0 != 0
  107. }
  108. /// Union of two role sets.
  109. pub const fn union(self, other: Role) -> Role {
  110. Role(self.0 | other.0)
  111. }
  112. }
  113. impl std::ops::BitOr for Role {
  114. type Output = Role;
  115. fn bitor(self, rhs: Role) -> Role {
  116. self.union(rhs)
  117. }
  118. }
  119. impl std::ops::BitOrAssign for Role {
  120. fn bitor_assign(&mut self, rhs: Role) {
  121. self.0 |= rhs.0;
  122. }
  123. }
  124. /// Read/write access masks for a property. Supply at creation; treat as
  125. /// immutable afterwards. The default allows every role, which preserves
  126. /// the pre-permission behavior for call sites that have not been
  127. /// assigned real masks yet.
  128. #[derive(Debug, Copy, Clone, PartialEq, Eq)]
  129. pub struct PropertyPermission {
  130. /// Roles allowed to read.
  131. pub read: Role,
  132. /// Roles allowed to write (set/unset/push/insert/remove/expr).
  133. pub write: Role,
  134. }
  135. impl Default for PropertyPermission {
  136. fn default() -> Self {
  137. Self { read: Role::ALL, write: Role::ALL }
  138. }
  139. }
  140. #[derive(Debug, Clone, PartialEq)]
  141. pub enum PropertyValue {
  142. Unset,
  143. Null,
  144. Bool(bool),
  145. Uint32(u32),
  146. Float32(f32),
  147. Str(String),
  148. Enum(String),
  149. SceneNodeId(SceneNodeId),
  150. SExpr(Arc<SExprCode>),
  151. VectorShape(Arc<VectorShape>),
  152. }
  153. impl PropertyValue {
  154. fn as_type(&self) -> PropertyType {
  155. match self {
  156. Self::Unset => todo!("not sure"),
  157. Self::Null => PropertyType::Null,
  158. Self::Bool(_) => PropertyType::Bool,
  159. Self::Uint32(_) => PropertyType::Uint32,
  160. Self::Float32(_) => PropertyType::Float32,
  161. Self::Str(_) => PropertyType::Str,
  162. Self::Enum(_) => PropertyType::Enum,
  163. Self::SceneNodeId(_) => PropertyType::SceneNodeId,
  164. Self::SExpr(_) => PropertyType::SExpr,
  165. Self::VectorShape(_) => PropertyType::VectorShape,
  166. }
  167. }
  168. pub fn is_unset(&self) -> bool {
  169. match self {
  170. Self::Unset => true,
  171. _ => false,
  172. }
  173. }
  174. pub fn is_null(&self) -> bool {
  175. match self {
  176. Self::Null => true,
  177. _ => false,
  178. }
  179. }
  180. pub fn is_expr(&self) -> bool {
  181. match self {
  182. Self::SExpr(_) => true,
  183. _ => false,
  184. }
  185. }
  186. pub fn as_bool(&self) -> Result<bool> {
  187. match self {
  188. Self::Bool(v) => Ok(*v),
  189. _ => Err(Error::PropertyWrongType),
  190. }
  191. }
  192. pub fn as_u32(&self) -> Result<u32> {
  193. match self {
  194. Self::Uint32(v) => Ok(*v),
  195. _ => Err(Error::PropertyWrongType),
  196. }
  197. }
  198. pub fn as_f32(&self) -> Result<f32> {
  199. match self {
  200. Self::Float32(v) => Ok(*v),
  201. _ => Err(Error::PropertyWrongType),
  202. }
  203. }
  204. pub fn as_str(&self) -> Result<String> {
  205. match self {
  206. Self::Str(v) => Ok(v.clone()),
  207. _ => Err(Error::PropertyWrongType),
  208. }
  209. }
  210. pub fn as_enum(&self) -> Result<String> {
  211. match self {
  212. Self::Enum(v) => Ok(v.clone()),
  213. _ => Err(Error::PropertyWrongType),
  214. }
  215. }
  216. pub fn as_node_id(&self) -> Result<SceneNodeId> {
  217. match self {
  218. Self::SceneNodeId(v) => Ok(*v),
  219. _ => Err(Error::PropertyWrongType),
  220. }
  221. }
  222. pub fn as_sexpr(&self) -> Result<Arc<SExprCode>> {
  223. match self {
  224. Self::SExpr(v) => Ok(v.clone()),
  225. _ => Err(Error::PropertyWrongType),
  226. }
  227. }
  228. pub fn as_shape(&self) -> Result<Arc<VectorShape>> {
  229. match self {
  230. Self::VectorShape(v) => Ok(v.clone()),
  231. _ => Err(Error::PropertyWrongType),
  232. }
  233. }
  234. }
  235. impl Encodable for PropertyValue {
  236. fn encode<S: Write>(&self, s: &mut S) -> std::result::Result<usize, std::io::Error> {
  237. match self {
  238. Self::Unset | Self::Null => {
  239. // do nothing
  240. Ok(0)
  241. }
  242. Self::Bool(v) => v.encode(s),
  243. Self::Uint32(v) => v.encode(s),
  244. Self::Float32(v) => v.encode(s),
  245. Self::Str(v) => v.encode(s),
  246. Self::Enum(v) => v.encode(s),
  247. Self::SceneNodeId(v) => v.encode(s),
  248. Self::SExpr(v) => v.encode(s),
  249. Self::VectorShape(v) => v.encode(s),
  250. }
  251. }
  252. }
  253. #[derive(Debug, Clone)]
  254. pub enum ModifyAction {
  255. Clear,
  256. Set(usize),
  257. SetVec,
  258. SetCache(Vec<usize>),
  259. Unset(usize),
  260. Push(usize),
  261. Insert(usize),
  262. Remove(usize, PropertyValue),
  263. /// The property's dependency list changed (edge added or removed).
  264. /// Control-plane, not a value mutation: `when_change` loops use it to
  265. /// resync their poll sets (design D5). Consumers that persist or
  266. /// forward value changes should ignore it.
  267. DependsChanged,
  268. }
  269. type ModifyPublisher = PublisherPtr<(Role, ModifyAction, BatchGuardPtr)>;
  270. pub type PropertyPtr = Arc<Property>;
  271. pub type PropertyWeak = Weak<Property>;
  272. #[derive(Debug, Clone)]
  273. pub struct PropertyDepend {
  274. pub prop: PropertyWeak,
  275. pub i: usize,
  276. pub local_name: String,
  277. }
  278. pub struct Property {
  279. pub name: String,
  280. pub node: SyncMutex<Option<SceneNodeWeak>>,
  281. pub typ: PropertyType,
  282. pub subtype: PropertySubType,
  283. // Defaults are construction-time metadata, but they can also be
  284. // installed post-creation (see `set_default_*`), so access is
  285. // synchronized like `vals`.
  286. pub defaults: SyncMutex<Vec<PropertyValue>>,
  287. // either a value or an expr must be set
  288. pub vals: SyncMutex<Vec<PropertyValue>>,
  289. // only used valid when PropertyValue is an expr
  290. // caches the last calculated value
  291. pub cache: SyncMutex<Vec<PropertyValue>>,
  292. pub ui_name: String,
  293. pub desc: String,
  294. pub is_null_allowed: bool,
  295. pub is_expr_allowed: bool,
  296. // Use 0 for unbounded length
  297. pub array_len: usize,
  298. pub min_val: Option<PropertyValue>,
  299. pub max_val: Option<PropertyValue>,
  300. // PropertyType must be Enum
  301. pub enum_items: Option<Vec<String>>,
  302. pub permission: PropertyPermission,
  303. on_modify: ModifyPublisher,
  304. depends: SyncMutex<Vec<PropertyDepend>>,
  305. }
  306. impl Property {
  307. pub fn new<S: Into<String>>(
  308. name: S,
  309. typ: PropertyType,
  310. subtype: PropertySubType,
  311. permission: PropertyPermission,
  312. ) -> Self {
  313. Self {
  314. name: name.into(),
  315. node: SyncMutex::new(None),
  316. typ,
  317. subtype,
  318. defaults: SyncMutex::new(vec![typ.default_value()]),
  319. vals: SyncMutex::new(vec![PropertyValue::Unset]),
  320. cache: SyncMutex::new(vec![PropertyValue::Null]),
  321. ui_name: String::new(),
  322. desc: String::new(),
  323. is_null_allowed: false,
  324. is_expr_allowed: false,
  325. array_len: 1,
  326. min_val: None,
  327. max_val: None,
  328. enum_items: None,
  329. permission,
  330. on_modify: Publisher::new(),
  331. depends: SyncMutex::new(vec![]),
  332. }
  333. }
  334. /// Just used for debugging
  335. pub fn set_parent(&self, node: SceneNodeWeak) {
  336. *self.node.lock().unwrap() = Some(node);
  337. }
  338. /// Read-mask check for the acting role.
  339. #[inline]
  340. pub fn can_read(&self, role: Role) -> bool {
  341. self.permission.read.contains(role)
  342. }
  343. /// Write-mask check for the acting role.
  344. #[inline]
  345. pub fn can_write(&self, role: Role) -> bool {
  346. self.permission.write.contains(role)
  347. }
  348. /// Central write enforcement: called at the top of every mutating
  349. /// API, before any mutation or guard journaling, so a denial leaves
  350. /// the property untouched. Exempt (by design): `set_default_*`
  351. /// (construction metadata), `set_cache_*` (derived eval artifacts),
  352. /// and `add_depend` (wiring metadata).
  353. #[inline]
  354. fn check_write(&self, role: Role) -> Result<()> {
  355. if self.can_write(role) {
  356. Ok(())
  357. } else {
  358. Err(Error::PropertyPermissionDenied)
  359. }
  360. }
  361. pub fn set_ui_text<S: Into<String>>(&mut self, ui_name: S, desc: S) {
  362. self.ui_name = ui_name.into();
  363. self.desc = desc.into();
  364. }
  365. pub fn set_array_len(&mut self, len: usize) {
  366. self.array_len = len;
  367. {
  368. let defaults = &mut self.defaults.lock().unwrap();
  369. defaults.resize(len, self.typ.default_value());
  370. defaults.shrink_to_fit();
  371. }
  372. let vals = &mut *self.vals.lock().unwrap();
  373. vals.resize(len, PropertyValue::Unset);
  374. vals.shrink_to_fit();
  375. let cache = &mut *self.cache.lock().unwrap();
  376. cache.resize(len, PropertyValue::Null);
  377. cache.shrink_to_fit();
  378. }
  379. pub fn set_unbounded(&mut self) {
  380. self.set_array_len(0);
  381. }
  382. pub fn set_range_u32(&mut self, min: u32, max: u32) {
  383. self.min_val = Some(PropertyValue::Uint32(min));
  384. self.max_val = Some(PropertyValue::Uint32(max));
  385. }
  386. pub fn set_range_f32(&mut self, min: f32, max: f32) {
  387. self.min_val = Some(PropertyValue::Float32(min));
  388. self.max_val = Some(PropertyValue::Float32(max));
  389. }
  390. pub fn set_enum_items<S: Into<String>>(&mut self, enum_items: Vec<S>) -> Result<()> {
  391. if self.typ != PropertyType::Enum {
  392. return Err(Error::PropertyWrongType)
  393. }
  394. self.enum_items = Some(enum_items.into_iter().map(|item| item.into()).collect());
  395. Ok(())
  396. }
  397. pub fn allow_null_values(&mut self) {
  398. self.is_null_allowed = true;
  399. }
  400. pub fn allow_exprs(&mut self) {
  401. self.is_expr_allowed = true;
  402. }
  403. fn check_defaults_len(&self, defaults_len: usize) -> Result<()> {
  404. if self.is_bounded() && defaults_len != self.array_len {
  405. return Err(Error::PropertyWrongLen)
  406. }
  407. Ok(())
  408. }
  409. pub fn set_defaults_bool(&mut self, defaults: Vec<bool>) -> Result<()> {
  410. self.check_defaults_len(defaults.len())?;
  411. *self.defaults.lock().unwrap() =
  412. defaults.into_iter().map(|v| PropertyValue::Bool(v)).collect();
  413. Ok(())
  414. }
  415. pub fn set_defaults_u32(&mut self, defaults: Vec<u32>) -> Result<()> {
  416. self.check_defaults_len(defaults.len())?;
  417. *self.defaults.lock().unwrap() =
  418. defaults.into_iter().map(|v| PropertyValue::Uint32(v)).collect();
  419. Ok(())
  420. }
  421. pub fn set_defaults_f32(&mut self, defaults: Vec<f32>) -> Result<()> {
  422. self.check_defaults_len(defaults.len())?;
  423. *self.defaults.lock().unwrap() =
  424. defaults.into_iter().map(|v| PropertyValue::Float32(v)).collect();
  425. Ok(())
  426. }
  427. pub fn set_defaults_str(&mut self, defaults: Vec<String>) -> Result<()> {
  428. self.check_defaults_len(defaults.len())?;
  429. *self.defaults.lock().unwrap() =
  430. defaults.into_iter().map(|v| PropertyValue::Str(v)).collect();
  431. Ok(())
  432. }
  433. pub fn set_defaults_null(&mut self) -> Result<()> {
  434. if !self.is_null_allowed {
  435. return Err(Error::PropertyNullNotAllowed)
  436. }
  437. if !self.is_bounded() {
  438. return Err(Error::PropertyWrongLen)
  439. }
  440. *self.defaults.lock().unwrap() = (0..self.array_len).map(|_| PropertyValue::Null).collect();
  441. Ok(())
  442. }
  443. /// Install expression defaults (builder variant). Requires `allow_exprs()`
  444. /// to have been called first, same as the post-creation variant.
  445. pub fn set_defaults_expr(&mut self, defaults: Vec<SExprCode>) -> Result<()> {
  446. if !self.is_expr_allowed {
  447. return Err(Error::PropertySExprNotAllowed)
  448. }
  449. self.check_defaults_len(defaults.len())?;
  450. *self.defaults.lock().unwrap() =
  451. defaults.into_iter().map(|v| PropertyValue::SExpr(Arc::new(v))).collect();
  452. Ok(())
  453. }
  454. // Post-creation default installation.
  455. //
  456. // Mutates `defaults[i]` on a live property with the same type/length
  457. // checks as the builder variants. Installing a default emits NO modify
  458. // event: it is a construction-time operation (before first frame) or
  459. // happens inside a switch batch where the accompanying unsets already
  460. // notify. Defaults are never mutated as a live styling mechanism.
  461. // Write masks do not apply (construction metadata).
  462. /// Raw variant; used by token-node construction. `SExpr` and `Null`
  463. /// are cross-type by design (mirroring `set_expr`/`set_null`) and are
  464. /// gated by `is_expr_allowed`/`is_null_allowed` instead.
  465. pub fn set_default_value(&self, i: usize, val: PropertyValue) -> Result<()> {
  466. match &val {
  467. PropertyValue::Unset => return Err(Error::PropertyWrongType),
  468. PropertyValue::SExpr(_) => {
  469. if !self.is_expr_allowed {
  470. return Err(Error::PropertySExprNotAllowed)
  471. }
  472. }
  473. PropertyValue::Null => {
  474. if !self.is_null_allowed {
  475. return Err(Error::PropertyNullNotAllowed)
  476. }
  477. }
  478. other => {
  479. if self.typ != other.as_type() {
  480. return Err(Error::PropertyWrongType)
  481. }
  482. }
  483. }
  484. let defaults = &mut self.defaults.lock().unwrap();
  485. if i >= defaults.len() {
  486. return Err(Error::PropertyWrongIndex)
  487. }
  488. defaults[i] = val;
  489. Ok(())
  490. }
  491. pub fn set_default_bool(&self, i: usize, val: bool) -> Result<()> {
  492. self.set_default_value(i, PropertyValue::Bool(val))
  493. }
  494. pub fn set_default_u32(&self, i: usize, val: u32) -> Result<()> {
  495. self.set_default_value(i, PropertyValue::Uint32(val))
  496. }
  497. pub fn set_default_f32(&self, i: usize, val: f32) -> Result<()> {
  498. self.set_default_value(i, PropertyValue::Float32(val))
  499. }
  500. /// Set all indices of a bounded array at once.
  501. pub fn set_default_f32_multi(&self, vals: &[f32]) -> Result<()> {
  502. if self.is_bounded() && vals.len() != self.array_len {
  503. return Err(Error::PropertyWrongLen)
  504. }
  505. let mut defaults = self.defaults.lock().unwrap();
  506. if self.is_bounded() {
  507. for (i, val) in vals.iter().enumerate() {
  508. defaults[i] = PropertyValue::Float32(*val);
  509. }
  510. } else {
  511. defaults.clear();
  512. defaults.extend(vals.iter().map(|v| PropertyValue::Float32(*v)));
  513. }
  514. Ok(())
  515. }
  516. pub fn set_default_str<S: Into<String>>(&self, i: usize, val: S) -> Result<()> {
  517. self.set_default_value(i, PropertyValue::Str(val.into()))
  518. }
  519. /// Writes a proper `PropertyValue::Enum` (unlike the builder
  520. /// `set_defaults_str`, which writes `Str` onto Enum properties) and
  521. /// validates the item against `enum_items`.
  522. pub fn set_default_enum<S: Into<String>>(&self, i: usize, val: S) -> Result<()> {
  523. if self.typ != PropertyType::Enum {
  524. return Err(Error::PropertyWrongType)
  525. }
  526. let val = val.into();
  527. if let Some(items) = &self.enum_items {
  528. if !items.contains(&val) {
  529. return Err(Error::PropertyWrongEnumItem)
  530. }
  531. }
  532. self.set_default_value(i, PropertyValue::Enum(val))
  533. }
  534. pub fn set_default_node_id(&self, i: usize, val: SceneNodeId) -> Result<()> {
  535. self.set_default_value(i, PropertyValue::SceneNodeId(val))
  536. }
  537. pub fn set_default_shape(&self, i: usize, val: VectorShape) -> Result<()> {
  538. self.set_default_value(i, PropertyValue::VectorShape(Arc::new(val)))
  539. }
  540. pub fn set_default_null(&self, i: usize) -> Result<()> {
  541. self.set_default_value(i, PropertyValue::Null)
  542. }
  543. /// Install an expression default on a live property. Requires the
  544. /// factory to have opted in via `allow_exprs()`.
  545. pub fn set_default_expr(&self, i: usize, code: SExprCode) -> Result<()> {
  546. self.set_default_value(i, PropertyValue::SExpr(Arc::new(code)))
  547. }
  548. // Set
  549. /// This will clear all values, resetting them to the default
  550. pub fn clear_values(
  551. self: &Arc<Self>,
  552. atom: &mut PropertyAtomicGuard,
  553. role: Role,
  554. ) -> Result<()> {
  555. self.check_write(role)?;
  556. {
  557. let vals = &mut self.vals.lock().unwrap();
  558. vals.clear();
  559. vals.resize(self.array_len, PropertyValue::Unset);
  560. }
  561. atom.add(self.clone(), role, ModifyAction::Clear);
  562. Ok(())
  563. }
  564. fn set_raw_value(&self, i: usize, val: PropertyValue) -> Result<()> {
  565. if self.typ != val.as_type() {
  566. return Err(Error::PropertyWrongType)
  567. }
  568. let vals = &mut self.vals.lock().unwrap();
  569. if i >= vals.len() {
  570. return Err(Error::PropertyWrongIndex)
  571. }
  572. vals[i] = val;
  573. Ok(())
  574. }
  575. pub fn unset(
  576. self: &Arc<Self>,
  577. atom: &mut PropertyAtomicGuard,
  578. role: Role,
  579. i: usize,
  580. ) -> Result<()> {
  581. self.check_write(role)?;
  582. {
  583. let vals = &mut self.vals.lock().unwrap();
  584. if i >= vals.len() {
  585. return Err(Error::PropertyWrongIndex)
  586. }
  587. vals[i] = PropertyValue::Unset;
  588. }
  589. atom.add(self.clone(), role, ModifyAction::Unset(i));
  590. Ok(())
  591. }
  592. pub fn set_null(
  593. self: &Arc<Self>,
  594. atom: &mut PropertyAtomicGuard,
  595. role: Role,
  596. i: usize,
  597. ) -> Result<()> {
  598. self.check_write(role)?;
  599. if !self.is_null_allowed {
  600. return Err(Error::PropertyNullNotAllowed)
  601. }
  602. let mut vals = self.vals.lock().unwrap();
  603. if i >= vals.len() {
  604. return Err(Error::PropertyWrongIndex)
  605. }
  606. vals[i] = PropertyValue::Null;
  607. drop(vals);
  608. atom.add(self.clone(), role, ModifyAction::Set(i));
  609. Ok(())
  610. }
  611. pub fn set_bool(
  612. self: &Arc<Self>,
  613. atom: &mut PropertyAtomicGuard,
  614. role: Role,
  615. i: usize,
  616. val: bool,
  617. ) -> Result<()> {
  618. self.check_write(role)?;
  619. self.set_raw_value(i, PropertyValue::Bool(val))?;
  620. atom.add(self.clone(), role, ModifyAction::Set(i));
  621. Ok(())
  622. }
  623. pub fn set_u32(
  624. self: &Arc<Self>,
  625. atom: &mut PropertyAtomicGuard,
  626. role: Role,
  627. i: usize,
  628. val: u32,
  629. ) -> Result<()> {
  630. self.check_write(role)?;
  631. if self.min_val.is_some() {
  632. let min = self.min_val.as_ref().unwrap().as_u32()?;
  633. if val < min {
  634. return Err(Error::PropertyOutOfRange)
  635. }
  636. }
  637. if self.max_val.is_some() {
  638. let max = self.max_val.as_ref().unwrap().as_u32()?;
  639. if val > max {
  640. return Err(Error::PropertyOutOfRange)
  641. }
  642. }
  643. self.set_raw_value(i, PropertyValue::Uint32(val))?;
  644. atom.add(self.clone(), role, ModifyAction::Set(i));
  645. Ok(())
  646. }
  647. pub fn set_f32(
  648. self: &Arc<Self>,
  649. atom: &mut PropertyAtomicGuard,
  650. role: Role,
  651. i: usize,
  652. val: f32,
  653. ) -> Result<()> {
  654. self.check_write(role)?;
  655. if self.min_val.is_some() {
  656. let min = self.min_val.as_ref().unwrap().as_f32()?;
  657. if val < min {
  658. return Err(Error::PropertyOutOfRange)
  659. }
  660. }
  661. if self.max_val.is_some() {
  662. let max = self.max_val.as_ref().unwrap().as_f32()?;
  663. if val > max {
  664. return Err(Error::PropertyOutOfRange)
  665. }
  666. }
  667. self.set_raw_value(i, PropertyValue::Float32(val))?;
  668. atom.add(self.clone(), role, ModifyAction::Set(i));
  669. Ok(())
  670. }
  671. pub fn set_str<S: Into<String>>(
  672. self: &Arc<Self>,
  673. atom: &mut PropertyAtomicGuard,
  674. role: Role,
  675. i: usize,
  676. val: S,
  677. ) -> Result<()> {
  678. self.check_write(role)?;
  679. self.set_raw_value(i, PropertyValue::Str(val.into()))?;
  680. atom.add(self.clone(), role, ModifyAction::Set(i));
  681. Ok(())
  682. }
  683. pub fn set_enum<S: Into<String>>(
  684. self: &Arc<Self>,
  685. atom: &mut PropertyAtomicGuard,
  686. role: Role,
  687. i: usize,
  688. val: S,
  689. ) -> Result<()> {
  690. self.check_write(role)?;
  691. if self.typ != PropertyType::Enum {
  692. return Err(Error::PropertyWrongType)
  693. }
  694. let val = val.into();
  695. if !self.enum_items.as_ref().unwrap().contains(&val) {
  696. return Err(Error::PropertyWrongEnumItem)
  697. }
  698. self.set_raw_value(i, PropertyValue::Enum(val.into()))?;
  699. atom.add(self.clone(), role, ModifyAction::Set(i));
  700. Ok(())
  701. }
  702. pub fn set_node_id(
  703. self: &Arc<Self>,
  704. atom: &mut PropertyAtomicGuard,
  705. role: Role,
  706. i: usize,
  707. val: SceneNodeId,
  708. ) -> Result<()> {
  709. self.check_write(role)?;
  710. self.set_raw_value(i, PropertyValue::SceneNodeId(val))?;
  711. atom.add(self.clone(), role, ModifyAction::Set(i));
  712. Ok(())
  713. }
  714. pub fn set_expr(
  715. self: &Arc<Self>,
  716. atom: &mut PropertyAtomicGuard,
  717. role: Role,
  718. i: usize,
  719. val: SExprCode,
  720. ) -> Result<()> {
  721. self.check_write(role)?;
  722. {
  723. if !self.is_expr_allowed {
  724. return Err(Error::PropertySExprNotAllowed)
  725. }
  726. let vals = &mut self.vals.lock().unwrap();
  727. if i >= vals.len() {
  728. return Err(Error::PropertyWrongIndex)
  729. }
  730. vals[i] = PropertyValue::SExpr(Arc::new(val));
  731. }
  732. atom.add(self.clone(), role, ModifyAction::Set(i));
  733. Ok(())
  734. }
  735. /// Typed dispatch over `PropertyValue`, routing through the typed
  736. /// setters so range/enum checks and write-mask enforcement apply.
  737. pub fn set_value(
  738. self: &Arc<Self>,
  739. atom: &mut PropertyAtomicGuard,
  740. role: Role,
  741. i: usize,
  742. val: PropertyValue,
  743. ) -> Result<()> {
  744. match val {
  745. PropertyValue::Unset => self.unset(atom, role, i),
  746. PropertyValue::Null => self.set_null(atom, role, i),
  747. PropertyValue::Bool(v) => self.set_bool(atom, role, i, v),
  748. PropertyValue::Uint32(v) => self.set_u32(atom, role, i, v),
  749. PropertyValue::Float32(v) => self.set_f32(atom, role, i, v),
  750. PropertyValue::Str(v) => self.set_str(atom, role, i, v),
  751. PropertyValue::Enum(v) => self.set_enum(atom, role, i, v),
  752. PropertyValue::SceneNodeId(v) => self.set_node_id(atom, role, i, v),
  753. PropertyValue::SExpr(v) => self.set_expr(atom, role, i, (*v).clone()),
  754. // VectorShape is not Clone and set_shape has no extra
  755. // checks beyond set_raw_value, so write the Arc directly.
  756. PropertyValue::VectorShape(_) => {
  757. self.check_write(role)?;
  758. self.set_raw_value(i, val)?;
  759. atom.add(self.clone(), role, ModifyAction::Set(i));
  760. Ok(())
  761. }
  762. }
  763. }
  764. pub fn set_shape(
  765. self: &Arc<Self>,
  766. atom: &mut PropertyAtomicGuard,
  767. role: Role,
  768. i: usize,
  769. val: VectorShape,
  770. ) -> Result<()> {
  771. self.check_write(role)?;
  772. self.set_raw_value(i, PropertyValue::VectorShape(Arc::new(val)))?;
  773. atom.add(self.clone(), role, ModifyAction::Set(i));
  774. Ok(())
  775. }
  776. fn set_value_vec<T, F>(
  777. self: &Arc<Self>,
  778. atom: &mut PropertyAtomicGuard,
  779. role: Role,
  780. val: Vec<T>,
  781. f: F,
  782. ) -> Result<()>
  783. where
  784. F: Fn(T) -> PropertyValue,
  785. {
  786. self.check_write(role)?;
  787. if self.is_bounded() {
  788. return Err(Error::PropertyIsBounded)
  789. }
  790. {
  791. let mut vals = self.vals.lock().unwrap();
  792. vals.clear();
  793. vals.extend(val.into_iter().map(f));
  794. }
  795. atom.add(self.clone(), role, ModifyAction::SetVec);
  796. Ok(())
  797. }
  798. pub fn set_bool_vec(
  799. self: &Arc<Self>,
  800. atom: &mut PropertyAtomicGuard,
  801. role: Role,
  802. val: Vec<bool>,
  803. ) -> Result<()> {
  804. self.set_value_vec(atom, role, val, PropertyValue::Bool)
  805. }
  806. pub fn set_u32_vec(
  807. self: &Arc<Self>,
  808. atom: &mut PropertyAtomicGuard,
  809. role: Role,
  810. val: Vec<u32>,
  811. ) -> Result<()> {
  812. self.set_value_vec(atom, role, val, PropertyValue::Uint32)
  813. }
  814. pub fn set_f32_vec(
  815. self: &Arc<Self>,
  816. atom: &mut PropertyAtomicGuard,
  817. role: Role,
  818. val: Vec<f32>,
  819. ) -> Result<()> {
  820. self.set_value_vec(atom, role, val, PropertyValue::Float32)
  821. }
  822. pub fn set_str_vec<S: Into<String>>(
  823. self: &Arc<Self>,
  824. atom: &mut PropertyAtomicGuard,
  825. role: Role,
  826. val: Vec<S>,
  827. ) -> Result<()> {
  828. self.set_value_vec(atom, role, val, |v| PropertyValue::Str(v.into()))
  829. }
  830. pub fn set_enum_vec<S: Into<String>>(
  831. self: &Arc<Self>,
  832. atom: &mut PropertyAtomicGuard,
  833. role: Role,
  834. val: Vec<S>,
  835. ) -> Result<()> {
  836. if self.typ != PropertyType::Enum {
  837. return Err(Error::PropertyWrongType)
  838. }
  839. self.set_value_vec(atom, role, val, |v| PropertyValue::Enum(v.into()))
  840. }
  841. pub fn set_node_id_vec(
  842. self: &Arc<Self>,
  843. atom: &mut PropertyAtomicGuard,
  844. role: Role,
  845. val: Vec<SceneNodeId>,
  846. ) -> Result<()> {
  847. self.set_value_vec(atom, role, val, PropertyValue::SceneNodeId)
  848. }
  849. fn set_cache(&self, i: usize, val: PropertyValue) -> Result<()> {
  850. if self.typ != val.as_type() {
  851. return Err(Error::PropertyWrongType)
  852. }
  853. let cache = &mut self.cache.lock().unwrap();
  854. if i >= cache.len() {
  855. return Err(Error::PropertyWrongIndex)
  856. }
  857. cache[i] = val;
  858. Ok(())
  859. }
  860. pub fn set_cache_f32(
  861. self: &Arc<Self>,
  862. atom: &mut PropertyAtomicGuard,
  863. role: Role,
  864. i: usize,
  865. val: f32,
  866. ) -> Result<()> {
  867. self.set_cache(i, PropertyValue::Float32(val))?;
  868. atom.add(self.clone(), role, ModifyAction::SetCache(vec![i]));
  869. Ok(())
  870. }
  871. pub fn set_cache_u32(
  872. self: &Arc<Self>,
  873. atom: &mut PropertyAtomicGuard,
  874. role: Role,
  875. i: usize,
  876. val: u32,
  877. ) -> Result<()> {
  878. self.set_cache(i, PropertyValue::Uint32(val))?;
  879. atom.add(self.clone(), role, ModifyAction::SetCache(vec![i]));
  880. Ok(())
  881. }
  882. pub fn set_cache_f32_multi(
  883. self: &Arc<Self>,
  884. atom: &mut PropertyAtomicGuard,
  885. role: Role,
  886. changes: Vec<(usize, f32)>,
  887. ) -> Result<()> {
  888. let mut idxs = vec![];
  889. for (idx, val) in changes {
  890. self.set_cache(idx, PropertyValue::Float32(val))?;
  891. idxs.push(idx);
  892. }
  893. atom.add(self.clone(), role, ModifyAction::SetCache(idxs));
  894. Ok(())
  895. }
  896. pub fn set_cache_u32_range(
  897. self: &Arc<Self>,
  898. atom: &mut PropertyAtomicGuard,
  899. role: Role,
  900. changes: Vec<(usize, u32)>,
  901. ) -> Result<()> {
  902. let mut idxs = vec![];
  903. for (idx, val) in changes {
  904. self.set_cache(idx, PropertyValue::Uint32(val))?;
  905. idxs.push(idx);
  906. }
  907. atom.add(self.clone(), role, ModifyAction::SetCache(idxs));
  908. Ok(())
  909. }
  910. // Push
  911. fn push_value(
  912. self: &Arc<Self>,
  913. atom: &mut PropertyAtomicGuard,
  914. role: Role,
  915. value: PropertyValue,
  916. ) -> Result<usize> {
  917. self.check_write(role)?;
  918. if self.is_bounded() {
  919. return Err(Error::PropertyIsBounded)
  920. }
  921. let mut vals = self.vals.lock().unwrap();
  922. let i = vals.len();
  923. vals.push(value);
  924. drop(vals);
  925. atom.add(self.clone(), role, ModifyAction::Push(i));
  926. Ok(i)
  927. }
  928. pub fn push_null(
  929. self: &Arc<Self>,
  930. atom: &mut PropertyAtomicGuard,
  931. role: Role,
  932. ) -> Result<usize> {
  933. self.push_value(atom, role, PropertyValue::Null)
  934. }
  935. pub fn push_bool(
  936. self: &Arc<Self>,
  937. atom: &mut PropertyAtomicGuard,
  938. role: Role,
  939. val: bool,
  940. ) -> Result<usize> {
  941. self.push_value(atom, role, PropertyValue::Bool(val))
  942. }
  943. pub fn push_u32(
  944. self: &Arc<Self>,
  945. atom: &mut PropertyAtomicGuard,
  946. role: Role,
  947. val: u32,
  948. ) -> Result<usize> {
  949. // TODO: none of these push calls are enforcing constraints that are required
  950. // see the set_XX calls.
  951. self.push_value(atom, role, PropertyValue::Uint32(val))
  952. }
  953. pub fn push_f32(
  954. self: &Arc<Self>,
  955. atom: &mut PropertyAtomicGuard,
  956. role: Role,
  957. val: f32,
  958. ) -> Result<usize> {
  959. self.push_value(atom, role, PropertyValue::Float32(val))
  960. }
  961. pub fn push_str<S: Into<String>>(
  962. self: &Arc<Self>,
  963. atom: &mut PropertyAtomicGuard,
  964. role: Role,
  965. val: S,
  966. ) -> Result<usize> {
  967. self.push_value(atom, role, PropertyValue::Str(val.into()))
  968. }
  969. pub fn push_enum<S: Into<String>>(
  970. self: &Arc<Self>,
  971. atom: &mut PropertyAtomicGuard,
  972. role: Role,
  973. val: S,
  974. ) -> Result<usize> {
  975. self.push_value(atom, role, PropertyValue::Enum(val.into()))
  976. }
  977. pub fn push_node_id(
  978. self: &Arc<Self>,
  979. atom: &mut PropertyAtomicGuard,
  980. role: Role,
  981. val: SceneNodeId,
  982. ) -> Result<usize> {
  983. self.push_value(atom, role, PropertyValue::SceneNodeId(val))
  984. }
  985. // Insert
  986. fn insert_value(
  987. self: &Arc<Self>,
  988. atom: &mut PropertyAtomicGuard,
  989. role: Role,
  990. index: usize,
  991. value: PropertyValue,
  992. ) -> Result<usize> {
  993. self.check_write(role)?;
  994. if self.is_bounded() {
  995. return Err(Error::PropertyIsBounded)
  996. }
  997. if index > self.get_len() {
  998. return Err(Error::PropertyWrongIndex)
  999. }
  1000. let mut vals = self.vals.lock().unwrap();
  1001. vals.insert(index, value);
  1002. drop(vals);
  1003. atom.add(self.clone(), role, ModifyAction::Insert(index));
  1004. Ok(index)
  1005. }
  1006. pub fn insert_null(
  1007. self: &Arc<Self>,
  1008. atom: &mut PropertyAtomicGuard,
  1009. role: Role,
  1010. index: usize,
  1011. ) -> Result<usize> {
  1012. self.insert_value(atom, role, index, PropertyValue::Null)
  1013. }
  1014. pub fn insert_bool(
  1015. self: &Arc<Self>,
  1016. atom: &mut PropertyAtomicGuard,
  1017. role: Role,
  1018. index: usize,
  1019. val: bool,
  1020. ) -> Result<usize> {
  1021. self.insert_value(atom, role, index, PropertyValue::Bool(val))
  1022. }
  1023. pub fn insert_u32(
  1024. self: &Arc<Self>,
  1025. atom: &mut PropertyAtomicGuard,
  1026. role: Role,
  1027. index: usize,
  1028. val: u32,
  1029. ) -> Result<usize> {
  1030. self.insert_value(atom, role, index, PropertyValue::Uint32(val))
  1031. }
  1032. pub fn insert_f32(
  1033. self: &Arc<Self>,
  1034. atom: &mut PropertyAtomicGuard,
  1035. role: Role,
  1036. index: usize,
  1037. val: f32,
  1038. ) -> Result<usize> {
  1039. self.insert_value(atom, role, index, PropertyValue::Float32(val))
  1040. }
  1041. pub fn insert_str<S: Into<String>>(
  1042. self: &Arc<Self>,
  1043. atom: &mut PropertyAtomicGuard,
  1044. role: Role,
  1045. index: usize,
  1046. val: S,
  1047. ) -> Result<usize> {
  1048. self.insert_value(atom, role, index, PropertyValue::Str(val.into()))
  1049. }
  1050. pub fn insert_enum<S: Into<String>>(
  1051. self: &Arc<Self>,
  1052. atom: &mut PropertyAtomicGuard,
  1053. role: Role,
  1054. index: usize,
  1055. val: S,
  1056. ) -> Result<usize> {
  1057. self.insert_value(atom, role, index, PropertyValue::Enum(val.into()))
  1058. }
  1059. pub fn insert_node_id(
  1060. self: &Arc<Self>,
  1061. atom: &mut PropertyAtomicGuard,
  1062. role: Role,
  1063. index: usize,
  1064. val: SceneNodeId,
  1065. ) -> Result<usize> {
  1066. self.insert_value(atom, role, index, PropertyValue::SceneNodeId(val))
  1067. }
  1068. // Remove
  1069. fn remove_value(
  1070. self: &Arc<Self>,
  1071. atom: &mut PropertyAtomicGuard,
  1072. role: Role,
  1073. index: usize,
  1074. ) -> Result<PropertyValue> {
  1075. self.check_write(role)?;
  1076. if self.is_bounded() {
  1077. return Err(Error::PropertyIsBounded)
  1078. }
  1079. if index >= self.get_len() {
  1080. return Err(Error::PropertyWrongIndex)
  1081. }
  1082. let mut vals = self.vals.lock().unwrap();
  1083. let value = vals.remove(index);
  1084. drop(vals);
  1085. atom.add(self.clone(), role, ModifyAction::Remove(index, value.clone()));
  1086. Ok(value)
  1087. }
  1088. pub fn remove_null(
  1089. self: &Arc<Self>,
  1090. atom: &mut PropertyAtomicGuard,
  1091. role: Role,
  1092. index: usize,
  1093. ) -> Result<()> {
  1094. self.remove_value(atom, role, index)?;
  1095. Ok(())
  1096. }
  1097. pub fn remove_bool(
  1098. self: &Arc<Self>,
  1099. atom: &mut PropertyAtomicGuard,
  1100. role: Role,
  1101. index: usize,
  1102. ) -> Result<bool> {
  1103. match self.remove_value(atom, role, index)? {
  1104. PropertyValue::Bool(v) => Ok(v),
  1105. _ => Err(Error::PropertyWrongType),
  1106. }
  1107. }
  1108. pub fn remove_u32(
  1109. self: &Arc<Self>,
  1110. atom: &mut PropertyAtomicGuard,
  1111. role: Role,
  1112. index: usize,
  1113. ) -> Result<u32> {
  1114. match self.remove_value(atom, role, index)? {
  1115. PropertyValue::Uint32(v) => Ok(v),
  1116. _ => Err(Error::PropertyWrongType),
  1117. }
  1118. }
  1119. pub fn remove_f32(
  1120. self: &Arc<Self>,
  1121. atom: &mut PropertyAtomicGuard,
  1122. role: Role,
  1123. index: usize,
  1124. ) -> Result<f32> {
  1125. match self.remove_value(atom, role, index)? {
  1126. PropertyValue::Float32(v) => Ok(v),
  1127. _ => Err(Error::PropertyWrongType),
  1128. }
  1129. }
  1130. pub fn remove_str(
  1131. self: &Arc<Self>,
  1132. atom: &mut PropertyAtomicGuard,
  1133. role: Role,
  1134. index: usize,
  1135. ) -> Result<String> {
  1136. match self.remove_value(atom, role, index)? {
  1137. PropertyValue::Str(v) => Ok(v),
  1138. _ => Err(Error::PropertyWrongType),
  1139. }
  1140. }
  1141. pub fn remove_enum(
  1142. self: &Arc<Self>,
  1143. atom: &mut PropertyAtomicGuard,
  1144. role: Role,
  1145. index: usize,
  1146. ) -> Result<String> {
  1147. match self.remove_value(atom, role, index)? {
  1148. PropertyValue::Enum(v) => Ok(v),
  1149. _ => Err(Error::PropertyWrongType),
  1150. }
  1151. }
  1152. pub fn remove_node_id(
  1153. self: &Arc<Self>,
  1154. atom: &mut PropertyAtomicGuard,
  1155. role: Role,
  1156. index: usize,
  1157. ) -> Result<SceneNodeId> {
  1158. match self.remove_value(atom, role, index)? {
  1159. PropertyValue::SceneNodeId(v) => Ok(v),
  1160. _ => Err(Error::PropertyWrongType),
  1161. }
  1162. }
  1163. // Remove by item
  1164. pub fn remove_str_item(
  1165. self: &Arc<Self>,
  1166. atom: &mut PropertyAtomicGuard,
  1167. role: Role,
  1168. item: &str,
  1169. ) -> Option<usize> {
  1170. for i in 0..self.get_len() {
  1171. if self.get_str(i).unwrap() == item {
  1172. self.remove_str(atom, role, i).unwrap();
  1173. return Some(i)
  1174. }
  1175. }
  1176. None
  1177. }
  1178. // Get
  1179. pub fn is_bounded(&self) -> bool {
  1180. self.array_len != 0
  1181. }
  1182. pub fn get_len(&self) -> usize {
  1183. // Avoid locking unless we need to
  1184. // If array len is nonzero, then vals len should be the same.
  1185. if !self.is_bounded() {
  1186. let vals_len = self.vals.lock().unwrap().len();
  1187. if vals_len > 0 {
  1188. return vals_len
  1189. }
  1190. return self.defaults.lock().unwrap().len()
  1191. }
  1192. self.array_len
  1193. }
  1194. pub fn is_unset(&self, i: usize) -> Result<bool> {
  1195. let val = self.get_raw_value(i)?;
  1196. Ok(val.is_unset())
  1197. }
  1198. pub fn is_null(&self, i: usize) -> Result<bool> {
  1199. let val = self.get_value(i)?;
  1200. Ok(val.is_null())
  1201. }
  1202. /// Effective-expression check: true when the active source for `i`
  1203. /// is an expression — the value slot's expression if present, else
  1204. /// (when the slot holds neither a plain value nor null) the
  1205. /// default's expression.
  1206. pub fn is_expr(&self, i: usize) -> Result<bool> {
  1207. if !self.is_expr_allowed {
  1208. return Ok(false)
  1209. }
  1210. let val = self.get_raw_value(i)?;
  1211. if val.is_expr() {
  1212. return Ok(true)
  1213. }
  1214. if !val.is_unset() {
  1215. return Ok(false)
  1216. }
  1217. let defaults = self.defaults.lock().unwrap();
  1218. if i >= defaults.len() {
  1219. return Err(Error::PropertyWrongIndex)
  1220. }
  1221. Ok(defaults[i].is_expr())
  1222. }
  1223. pub fn get_raw_value(&self, i: usize) -> Result<PropertyValue> {
  1224. let vals = &self.vals.lock().unwrap();
  1225. if self.is_bounded() {
  1226. assert_eq!(vals.len(), self.array_len);
  1227. }
  1228. if i >= vals.len() {
  1229. return Err(Error::PropertyWrongIndex)
  1230. }
  1231. let val = vals[i].clone();
  1232. Ok(val)
  1233. }
  1234. /// The effective expression source: the value slot's expression if
  1235. /// present, else the default's expression (when the slot is unset).
  1236. /// Errors when neither slot supplies one.
  1237. pub fn get_expr(&self, i: usize) -> Result<Arc<SExprCode>> {
  1238. let val = self.get_raw_value(i)?;
  1239. if val.is_expr() {
  1240. return val.as_sexpr()
  1241. }
  1242. if val.is_unset() {
  1243. let defaults = self.defaults.lock().unwrap();
  1244. if i >= defaults.len() {
  1245. return Err(Error::PropertyWrongIndex)
  1246. }
  1247. if let PropertyValue::SExpr(code) = &defaults[i] {
  1248. return Ok(code.clone())
  1249. }
  1250. }
  1251. Err(Error::PropertyWrongType)
  1252. }
  1253. /// Effective value: NEVER an unresolved expression. Resolution
  1254. /// order: set value → set expression's last computed result →
  1255. /// default → default expression's last computed result → type
  1256. /// default. One cache per index is shared between the two
  1257. /// expression sources; draw-side evaluation recomputes every expr
  1258. /// index each pass, so a stale cache after a source switch is
  1259. /// unobservable past the next pass (which the switch triggers).
  1260. pub fn get_value(&self, i: usize) -> Result<PropertyValue> {
  1261. // Unbounded with empty vals: the defaults list IS the value
  1262. // (theme unload clears vals → baseline palette shows through).
  1263. if !self.is_bounded() {
  1264. let vals = self.vals.lock().unwrap();
  1265. if vals.is_empty() {
  1266. drop(vals);
  1267. let defaults = self.defaults.lock().unwrap();
  1268. if i < defaults.len() {
  1269. return Ok(defaults[i].clone())
  1270. }
  1271. return Err(Error::PropertyWrongIndex)
  1272. }
  1273. }
  1274. let val = self.get_raw_value(i)?;
  1275. match val {
  1276. PropertyValue::SExpr(_) => {
  1277. let cached = self.get_cached(i)?;
  1278. if !cached.is_null() {
  1279. return Ok(cached)
  1280. }
  1281. // fall through to the default layer
  1282. Ok(self.default_or_type_default(i))
  1283. }
  1284. PropertyValue::Unset => Ok(self.default_or_type_default(i)),
  1285. v => Ok(v),
  1286. }
  1287. }
  1288. /// Default layer: plain default → default-expr cache → type default.
  1289. fn default_or_type_default(&self, i: usize) -> PropertyValue {
  1290. let defaults = self.defaults.lock().unwrap();
  1291. match &defaults[i] {
  1292. PropertyValue::SExpr(_) => match self.get_cached(i) {
  1293. Ok(c) if !c.is_null() => c,
  1294. _ => self.typ.default_value(),
  1295. },
  1296. d => d.clone(),
  1297. }
  1298. }
  1299. pub fn get_bool(&self, i: usize) -> Result<bool> {
  1300. self.get_value(i)?.as_bool()
  1301. }
  1302. pub fn get_bool_opt(&self, i: usize) -> Result<Option<bool>> {
  1303. let val = self.get_value(i)?;
  1304. if val.is_null() {
  1305. return Ok(None)
  1306. }
  1307. Ok(Some(val.as_bool()?))
  1308. }
  1309. pub fn get_u32(&self, i: usize) -> Result<u32> {
  1310. self.get_value(i)?.as_u32()
  1311. }
  1312. pub fn get_u32_opt(&self, i: usize) -> Result<Option<u32>> {
  1313. let val = self.get_value(i)?;
  1314. if val.is_null() {
  1315. return Ok(None)
  1316. }
  1317. Ok(Some(val.as_u32()?))
  1318. }
  1319. pub fn get_f32(&self, i: usize) -> Result<f32> {
  1320. self.get_value(i)?.as_f32()
  1321. }
  1322. pub fn get_f32_opt(&self, i: usize) -> Result<Option<f32>> {
  1323. let val = self.get_value(i)?;
  1324. if val.is_null() {
  1325. return Ok(None)
  1326. }
  1327. Ok(Some(val.as_f32()?))
  1328. }
  1329. pub fn get_str(&self, i: usize) -> Result<String> {
  1330. self.get_value(i)?.as_str()
  1331. }
  1332. pub fn get_str_opt(&self, i: usize) -> Result<Option<String>> {
  1333. let val = self.get_value(i)?;
  1334. if val.is_null() {
  1335. return Ok(None)
  1336. }
  1337. Ok(Some(val.as_str()?))
  1338. }
  1339. pub fn get_enum(&self, i: usize) -> Result<String> {
  1340. self.get_value(i)?.as_enum()
  1341. }
  1342. pub fn get_enum_opt(&self, i: usize) -> Result<Option<String>> {
  1343. let val = self.get_value(i)?;
  1344. if val.is_null() {
  1345. return Ok(None)
  1346. }
  1347. Ok(Some(val.as_enum()?))
  1348. }
  1349. pub fn get_node_id(&self, i: usize) -> Result<SceneNodeId> {
  1350. self.get_value(i)?.as_node_id()
  1351. }
  1352. pub fn get_node_id_opt(&self, i: usize) -> Result<Option<SceneNodeId>> {
  1353. let val = self.get_value(i)?;
  1354. if val.is_null() {
  1355. return Ok(None)
  1356. }
  1357. Ok(Some(val.as_node_id()?))
  1358. }
  1359. pub fn get_shape(&self, i: usize) -> Result<Arc<VectorShape>> {
  1360. self.get_value(i)?.as_shape()
  1361. }
  1362. pub fn get_cached(&self, i: usize) -> Result<PropertyValue> {
  1363. let cache = &self.cache.lock().unwrap();
  1364. if self.is_bounded() {
  1365. assert_eq!(cache.len(), self.array_len);
  1366. }
  1367. if i >= cache.len() {
  1368. return Err(Error::PropertyWrongIndex)
  1369. }
  1370. Ok(cache[i].clone())
  1371. }
  1372. fn get_value_vec<T, F>(&self, f: F) -> Result<Vec<T>>
  1373. where
  1374. F: Fn(&PropertyValue) -> Option<T>,
  1375. {
  1376. if self.is_bounded() {
  1377. return Err(Error::PropertyIsBounded)
  1378. }
  1379. let vals = self.vals.lock().unwrap();
  1380. let mut result = Vec::with_capacity(vals.len());
  1381. for val in vals.iter() {
  1382. match f(val) {
  1383. Some(v) => result.push(v),
  1384. None => return Err(Error::PropertyWrongType),
  1385. }
  1386. }
  1387. Ok(result)
  1388. }
  1389. pub fn get_bool_vec(&self) -> Result<Vec<bool>> {
  1390. self.get_value_vec(|val| match val {
  1391. PropertyValue::Bool(v) => Some(*v),
  1392. _ => None,
  1393. })
  1394. }
  1395. pub fn get_u32_vec(&self) -> Result<Vec<u32>> {
  1396. self.get_value_vec(|val| match val {
  1397. PropertyValue::Uint32(v) => Some(*v),
  1398. _ => None,
  1399. })
  1400. }
  1401. pub fn get_f32_vec(&self) -> Result<Vec<f32>> {
  1402. self.get_value_vec(|val| match val {
  1403. PropertyValue::Float32(v) => Some(*v),
  1404. _ => None,
  1405. })
  1406. }
  1407. pub fn get_str_vec(&self) -> Result<Vec<String>> {
  1408. self.get_value_vec(|val| match val {
  1409. PropertyValue::Str(v) => Some(v.clone()),
  1410. _ => None,
  1411. })
  1412. }
  1413. pub fn get_enum_vec(&self) -> Result<Vec<String>> {
  1414. self.get_value_vec(|val| match val {
  1415. PropertyValue::Enum(v) => Some(v.clone()),
  1416. _ => None,
  1417. })
  1418. }
  1419. pub fn get_node_id_vec(&self) -> Result<Vec<SceneNodeId>> {
  1420. self.get_value_vec(|val| match val {
  1421. PropertyValue::SceneNodeId(v) => Some(*v),
  1422. _ => None,
  1423. })
  1424. }
  1425. // Contains
  1426. pub fn contains_str(&self, s: &str) -> bool {
  1427. for i in 0..self.get_len() {
  1428. if let Ok(item) = self.get_str(i) {
  1429. if item == s {
  1430. return true
  1431. }
  1432. }
  1433. }
  1434. false
  1435. }
  1436. // Subs
  1437. pub fn subscribe_modify(&self) -> Subscription<(Role, ModifyAction, BatchGuardPtr)> {
  1438. self.on_modify.clone().subscribe()
  1439. }
  1440. // Dependencies
  1441. pub fn add_depend<S: Into<String>>(
  1442. &self,
  1443. role: Role,
  1444. prop: &PropertyPtr,
  1445. i: usize,
  1446. local_name: S,
  1447. ) {
  1448. self.depends.lock().unwrap().push(PropertyDepend {
  1449. prop: Arc::downgrade(prop),
  1450. i,
  1451. local_name: local_name.into(),
  1452. });
  1453. // Wake live subscribers so they resync their poll sets (D5);
  1454. // buffered events cover tasks that have not started polling yet.
  1455. self.on_modify.notify((role, ModifyAction::DependsChanged, guard::BatchGuard::detached()));
  1456. }
  1457. /// Remove edges matching `(dep prop, index, local name)`. Theme
  1458. /// unload restores original wiring with it: repeated switches must
  1459. /// not accumulate stale edges pointing at dead token nodes.
  1460. pub fn remove_depend(&self, role: Role, prop: &PropertyPtr, i: usize, local_name: &str) {
  1461. let depends = &mut self.depends.lock().unwrap();
  1462. depends.retain(|dep| {
  1463. !(dep.i == i && dep.local_name == local_name && dep.prop.ptr_eq(&Arc::downgrade(prop)))
  1464. });
  1465. drop(depends);
  1466. self.on_modify.notify((role, ModifyAction::DependsChanged, guard::BatchGuard::detached()));
  1467. }
  1468. pub fn get_depends(&self) -> Vec<PropertyDepend> {
  1469. self.depends.lock().unwrap().clone()
  1470. }
  1471. }
  1472. impl std::fmt::Debug for Property {
  1473. fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  1474. let node = {
  1475. let mut null_name = || write!(f, "<null>:{}", self.name);
  1476. let Ok(node) = self.node.lock() else { return null_name() };
  1477. let Some(node) = node.clone() else { return null_name() };
  1478. let Some(node) = node.upgrade() else { return null_name() };
  1479. node
  1480. };
  1481. write!(f, "{:?}:{}", node, self.name)
  1482. }
  1483. }
  1484. #[cfg(test)]
  1485. mod tests {
  1486. use super::*;
  1487. use crate::{expr::Op, ui::VectorShape as Shape};
  1488. #[test]
  1489. fn test_shape() {
  1490. let mut shape = Shape::new();
  1491. shape.add_filled_box(
  1492. vec![Op::ConstFloat32(0.)],
  1493. vec![Op::ConstFloat32(0.)],
  1494. vec![Op::ConstFloat32(10.)],
  1495. vec![Op::ConstFloat32(10.)],
  1496. [0., 0., 0., 1.],
  1497. );
  1498. let prop = Arc::new(Property::new(
  1499. "shape",
  1500. PropertyType::VectorShape,
  1501. PropertySubType::Null,
  1502. PropertyPermission::default(),
  1503. ));
  1504. let atom = &mut PropertyAtomicGuard::none();
  1505. // Default is an empty shape
  1506. assert_eq!(prop.get_shape(0).unwrap().verts.len(), 0);
  1507. prop.set_shape(atom, Role::App, 0, shape).unwrap();
  1508. assert_eq!(prop.get_shape(0).unwrap().verts.len(), 4);
  1509. assert_eq!(prop.get_shape(0).unwrap().indices.len(), 6);
  1510. // Wrong index
  1511. assert!(prop.set_shape(atom, Role::App, 4, Shape::new()).is_err());
  1512. }
  1513. #[test]
  1514. fn test_getset() {
  1515. let prop = Arc::new(Property::new(
  1516. "foo",
  1517. PropertyType::Float32,
  1518. PropertySubType::Null,
  1519. PropertyPermission::default(),
  1520. ));
  1521. let atom = &mut PropertyAtomicGuard::none();
  1522. assert!(prop.set_f32(atom, Role::App, 1, 4.).is_err());
  1523. assert!(prop.is_unset(0).unwrap());
  1524. assert!(prop.set_f32(atom, Role::App, 0, 4.).is_ok());
  1525. assert_eq!(prop.get_f32(0).unwrap(), 4.);
  1526. assert!(!prop.is_unset(0).unwrap());
  1527. prop.unset(atom, Role::App, 0).unwrap();
  1528. assert!(prop.is_unset(0).unwrap());
  1529. assert_eq!(prop.get_f32(0).unwrap(), 0.);
  1530. }
  1531. #[test]
  1532. fn test_nullable() {
  1533. // default len is 1
  1534. let mut prop_temp = Property::new(
  1535. "foo",
  1536. PropertyType::Float32,
  1537. PropertySubType::Null,
  1538. PropertyPermission::default(),
  1539. );
  1540. assert!(prop_temp.set_defaults_f32(vec![1.0, 0.0]).is_err());
  1541. assert!(prop_temp.set_defaults_f32(vec![2.0]).is_ok());
  1542. prop_temp.allow_null_values();
  1543. let prop = Arc::new(prop_temp);
  1544. let atom = &mut PropertyAtomicGuard::none();
  1545. prop.set_null(atom, Role::App, 0).unwrap();
  1546. assert!(prop.get_f32_opt(1).is_err());
  1547. assert!(prop.get_f32_opt(0).is_ok());
  1548. assert!(prop.get_f32_opt(0).unwrap().is_none());
  1549. prop.clear_values(atom, Role::App).unwrap();
  1550. assert!(prop.get_f32(0).is_ok());
  1551. assert!(prop.get_f32_opt(0).unwrap().is_some());
  1552. assert_eq!(prop.get_f32(0).unwrap(), 2.0);
  1553. }
  1554. #[test]
  1555. fn test_nonnullable() {
  1556. let prop = Arc::new(Property::new(
  1557. "foo",
  1558. PropertyType::Float32,
  1559. PropertySubType::Null,
  1560. PropertyPermission::default(),
  1561. ));
  1562. let atom = &mut PropertyAtomicGuard::none();
  1563. assert!(prop.set_null(atom, Role::App, 0).is_err());
  1564. assert!(prop.is_unset(0).unwrap());
  1565. }
  1566. #[test]
  1567. fn test_unbounded() {
  1568. let mut prop_temp = Property::new(
  1569. "foo",
  1570. PropertyType::Float32,
  1571. PropertySubType::Null,
  1572. PropertyPermission::default(),
  1573. );
  1574. prop_temp.set_unbounded();
  1575. prop_temp.allow_null_values();
  1576. let prop = Arc::new(prop_temp);
  1577. let atom = &mut PropertyAtomicGuard::none();
  1578. assert_eq!(prop.get_len(), 0);
  1579. prop.push_f32(atom, Role::App, 2.0).unwrap();
  1580. prop.push_f32(atom, Role::App, 3.0).unwrap();
  1581. assert_eq!(prop.get_len(), 2);
  1582. prop.clear_values(atom, Role::App).unwrap();
  1583. assert_eq!(prop.get_len(), 0);
  1584. prop.push_null(atom, Role::App).unwrap();
  1585. prop.push_f32(atom, Role::App, 4.0).unwrap();
  1586. prop.push_f32(atom, Role::App, 5.0).unwrap();
  1587. assert_eq!(prop.get_len(), 3);
  1588. assert!(prop.get_f32_opt(0).unwrap().is_none());
  1589. assert!(prop.get_f32_opt(1).unwrap().is_some());
  1590. assert!(prop.get_f32_opt(2).unwrap().is_some());
  1591. assert!(prop.get_f32_opt(3).is_err());
  1592. let prop2 = Arc::new(Property::new(
  1593. "foo",
  1594. PropertyType::Float32,
  1595. PropertySubType::Null,
  1596. PropertyPermission::default(),
  1597. ));
  1598. let atom2 = &mut PropertyAtomicGuard::none();
  1599. assert!(prop2.push_f32(atom2, Role::App, 4.0).is_err());
  1600. }
  1601. #[test]
  1602. fn test_range() {
  1603. let mut prop_temp = Property::new(
  1604. "foo",
  1605. PropertyType::Float32,
  1606. PropertySubType::Null,
  1607. PropertyPermission::default(),
  1608. );
  1609. let half_pi = 3.1415926535 / 2.;
  1610. prop_temp.set_range_f32(-half_pi, half_pi);
  1611. let prop = Arc::new(prop_temp);
  1612. let atom = &mut PropertyAtomicGuard::none();
  1613. assert!(prop.set_f32(atom, Role::App, 0, 6.).is_err());
  1614. assert!(prop.set_f32(atom, Role::App, 0, 1.).is_ok());
  1615. }
  1616. #[test]
  1617. fn test_enum() {
  1618. let mut prop_temp = Property::new(
  1619. "foo",
  1620. PropertyType::Enum,
  1621. PropertySubType::Null,
  1622. PropertyPermission::default(),
  1623. );
  1624. prop_temp.set_enum_items(vec!["ABC", "XYZ", "FOO"]).unwrap();
  1625. let prop = Arc::new(prop_temp);
  1626. let atom = &mut PropertyAtomicGuard::none();
  1627. assert!(prop.set_enum(atom, Role::App, 0, "ABC").is_ok());
  1628. assert!(prop.set_enum(atom, Role::App, 0, "BAR").is_err());
  1629. }
  1630. #[test]
  1631. fn test_expr() {
  1632. let mut prop_temp = Property::new(
  1633. "foo",
  1634. PropertyType::Float32,
  1635. PropertySubType::Null,
  1636. PropertyPermission::default(),
  1637. );
  1638. prop_temp.allow_exprs();
  1639. let prop = Arc::new(prop_temp);
  1640. let atom = &mut PropertyAtomicGuard::none();
  1641. assert_eq!(prop.get_f32(0).unwrap(), 0.);
  1642. let code = vec![Op::ConstFloat32(4.)];
  1643. prop.set_expr(atom, Role::App, 0, code).unwrap();
  1644. let val = prop.get_cached(0).unwrap();
  1645. assert!(val.is_null());
  1646. prop.set_cache_f32(atom, Role::App, 0, 4.).unwrap();
  1647. let val = prop.get_cached(0).unwrap();
  1648. assert_eq!(val.as_f32().unwrap(), 4.);
  1649. }
  1650. fn setup_test_property() -> Arc<Property> {
  1651. let mut prop_temp = Property::new(
  1652. "test",
  1653. PropertyType::Str,
  1654. PropertySubType::Null,
  1655. PropertyPermission::default(),
  1656. );
  1657. prop_temp.set_unbounded();
  1658. let prop = Arc::new(prop_temp);
  1659. let atom = &mut PropertyAtomicGuard::none();
  1660. prop.push_str(atom, Role::Internal, "Item 1").unwrap();
  1661. prop.push_str(atom, Role::Internal, "Item 2").unwrap();
  1662. prop.push_str(atom, Role::Internal, "Item 3").unwrap();
  1663. prop
  1664. }
  1665. #[test]
  1666. fn test_insert_at_beginning() {
  1667. let prop = setup_test_property();
  1668. let atom = &mut PropertyAtomicGuard::none();
  1669. prop.insert_str(atom, Role::App, 0, "NEW").unwrap();
  1670. assert_eq!(prop.get_len(), 4);
  1671. assert_eq!(prop.get_str(0).unwrap(), "NEW");
  1672. assert_eq!(prop.get_str(1).unwrap(), "Item 1");
  1673. assert_eq!(prop.get_str(2).unwrap(), "Item 2");
  1674. assert_eq!(prop.get_str(3).unwrap(), "Item 3");
  1675. }
  1676. #[test]
  1677. fn test_insert_at_end() {
  1678. let prop = setup_test_property();
  1679. let atom = &mut PropertyAtomicGuard::none();
  1680. prop.insert_str(atom, Role::App, 3, "NEW").unwrap();
  1681. assert_eq!(prop.get_len(), 4);
  1682. assert_eq!(prop.get_str(0).unwrap(), "Item 1");
  1683. assert_eq!(prop.get_str(1).unwrap(), "Item 2");
  1684. assert_eq!(prop.get_str(2).unwrap(), "Item 3");
  1685. assert_eq!(prop.get_str(3).unwrap(), "NEW");
  1686. }
  1687. #[test]
  1688. fn test_insert_in_middle() {
  1689. let prop = setup_test_property();
  1690. let atom = &mut PropertyAtomicGuard::none();
  1691. prop.insert_str(atom, Role::App, 1, "NEW").unwrap();
  1692. assert_eq!(prop.get_len(), 4);
  1693. assert_eq!(prop.get_str(0).unwrap(), "Item 1");
  1694. assert_eq!(prop.get_str(1).unwrap(), "NEW");
  1695. assert_eq!(prop.get_str(2).unwrap(), "Item 2");
  1696. assert_eq!(prop.get_str(3).unwrap(), "Item 3");
  1697. }
  1698. #[test]
  1699. fn test_insert_bounded_fails() {
  1700. let mut prop_temp = Property::new(
  1701. "test",
  1702. PropertyType::Str,
  1703. PropertySubType::Null,
  1704. PropertyPermission::default(),
  1705. );
  1706. prop_temp.set_array_len(3);
  1707. let prop = Arc::new(prop_temp);
  1708. let atom = &mut PropertyAtomicGuard::none();
  1709. let result = prop.insert_str(atom, Role::App, 0, "NEW");
  1710. assert!(matches!(result, Err(Error::PropertyIsBounded)));
  1711. }
  1712. #[test]
  1713. fn test_insert_out_of_bounds_fails() {
  1714. let prop = setup_test_property();
  1715. let atom = &mut PropertyAtomicGuard::none();
  1716. let result = prop.insert_str(atom, Role::App, 10, "NEW");
  1717. assert!(matches!(result, Err(Error::PropertyWrongIndex)));
  1718. }
  1719. #[test]
  1720. fn test_remove_from_beginning() {
  1721. let prop = setup_test_property();
  1722. let atom = &mut PropertyAtomicGuard::none();
  1723. let removed = prop.remove_str(atom, Role::App, 0).unwrap();
  1724. assert_eq!(removed, "Item 1");
  1725. assert_eq!(prop.get_len(), 2);
  1726. assert_eq!(prop.get_str(0).unwrap(), "Item 2");
  1727. assert_eq!(prop.get_str(1).unwrap(), "Item 3");
  1728. }
  1729. #[test]
  1730. fn test_remove_from_end() {
  1731. let prop = setup_test_property();
  1732. let atom = &mut PropertyAtomicGuard::none();
  1733. let removed = prop.remove_str(atom, Role::App, 2).unwrap();
  1734. assert_eq!(removed, "Item 3");
  1735. assert_eq!(prop.get_len(), 2);
  1736. assert_eq!(prop.get_str(0).unwrap(), "Item 1");
  1737. assert_eq!(prop.get_str(1).unwrap(), "Item 2");
  1738. }
  1739. #[test]
  1740. fn test_remove_from_middle() {
  1741. let prop = setup_test_property();
  1742. let atom = &mut PropertyAtomicGuard::none();
  1743. let removed = prop.remove_str(atom, Role::App, 1).unwrap();
  1744. assert_eq!(removed, "Item 2");
  1745. assert_eq!(prop.get_len(), 2);
  1746. assert_eq!(prop.get_str(0).unwrap(), "Item 1");
  1747. assert_eq!(prop.get_str(1).unwrap(), "Item 3");
  1748. }
  1749. #[test]
  1750. fn test_remove_bounded_fails() {
  1751. let mut prop_temp = Property::new(
  1752. "test",
  1753. PropertyType::Str,
  1754. PropertySubType::Null,
  1755. PropertyPermission::default(),
  1756. );
  1757. prop_temp.set_array_len(3);
  1758. let prop = Arc::new(prop_temp);
  1759. let atom = &mut PropertyAtomicGuard::none();
  1760. let result = prop.remove_str(atom, Role::App, 0);
  1761. assert!(matches!(result, Err(Error::PropertyIsBounded)));
  1762. }
  1763. #[test]
  1764. fn test_remove_out_of_bounds_fails() {
  1765. let prop = setup_test_property();
  1766. let atom = &mut PropertyAtomicGuard::none();
  1767. let result = prop.remove_str(atom, Role::App, 10);
  1768. assert!(matches!(result, Err(Error::PropertyWrongIndex)));
  1769. }
  1770. #[test]
  1771. fn test_insert_remove_mixed_types() {
  1772. let mut prop_temp = Property::new(
  1773. "test",
  1774. PropertyType::Float32,
  1775. PropertySubType::Null,
  1776. PropertyPermission::default(),
  1777. );
  1778. prop_temp.set_unbounded();
  1779. let prop = Arc::new(prop_temp);
  1780. let atom = &mut PropertyAtomicGuard::none();
  1781. prop.push_f32(atom, Role::App, 1.0).unwrap();
  1782. prop.push_f32(atom, Role::App, 3.0).unwrap();
  1783. prop.insert_f32(atom, Role::App, 1, 2.0).unwrap();
  1784. assert_eq!(prop.get_f32(0).unwrap(), 1.0);
  1785. assert_eq!(prop.get_f32(1).unwrap(), 2.0);
  1786. assert_eq!(prop.get_f32(2).unwrap(), 3.0);
  1787. let removed = prop.remove_f32(atom, Role::App, 1).unwrap();
  1788. assert_eq!(removed, 2.0);
  1789. assert_eq!(prop.get_len(), 2);
  1790. assert_eq!(prop.get_f32(0).unwrap(), 1.0);
  1791. assert_eq!(prop.get_f32(1).unwrap(), 3.0);
  1792. }
  1793. // ------------------------------------------------------------------
  1794. // Post-creation default installation (task 2.1)
  1795. // ------------------------------------------------------------------
  1796. #[test]
  1797. fn test_default_install_on_live_property() {
  1798. // A live (Arc'd, "linked") property whose value is unset reads the
  1799. // installed default once one is installed.
  1800. let prop = Arc::new(Property::new(
  1801. "foo",
  1802. PropertyType::Float32,
  1803. PropertySubType::Null,
  1804. PropertyPermission::default(),
  1805. ));
  1806. let atom = &mut PropertyAtomicGuard::none();
  1807. assert_eq!(prop.get_f32(0).unwrap(), 0.);
  1808. prop.set_default_f32(0, 42.).unwrap();
  1809. assert_eq!(prop.get_f32(0).unwrap(), 42.);
  1810. // Explicit value wins over the installed default
  1811. prop.set_f32(atom, Role::App, 0, 7.).unwrap();
  1812. assert_eq!(prop.get_f32(0).unwrap(), 7.);
  1813. // Clearing the value falls back to the default again
  1814. prop.unset(atom, Role::App, 0).unwrap();
  1815. assert_eq!(prop.get_f32(0).unwrap(), 42.);
  1816. }
  1817. #[test]
  1818. fn test_default_install_checks() {
  1819. // Wrong type
  1820. let prop = Arc::new(Property::new(
  1821. "foo",
  1822. PropertyType::Float32,
  1823. PropertySubType::Null,
  1824. PropertyPermission::default(),
  1825. ));
  1826. assert!(prop.set_default_bool(0, true).is_err());
  1827. // Wrong index
  1828. assert!(prop.set_default_f32(1, 1.).is_err());
  1829. // Unbounded properties reject per-index defaults (no defaults tier)
  1830. let mut temp = Property::new(
  1831. "foo",
  1832. PropertyType::Float32,
  1833. PropertySubType::Null,
  1834. PropertyPermission::default(),
  1835. );
  1836. temp.set_unbounded();
  1837. let prop = Arc::new(temp);
  1838. assert!(prop.set_default_f32(0, 1.).is_err());
  1839. // Enum default validates items and writes the Enum variant
  1840. let mut temp = Property::new(
  1841. "foo",
  1842. PropertyType::Enum,
  1843. PropertySubType::Null,
  1844. PropertyPermission::default(),
  1845. );
  1846. temp.set_enum_items(vec!["A", "B"]).unwrap();
  1847. let prop = Arc::new(temp);
  1848. assert!(prop.set_default_enum(0, "C").is_err());
  1849. prop.set_default_enum(0, "B").unwrap();
  1850. assert!(matches!(prop.get_value(0).unwrap(), PropertyValue::Enum(v) if v == "B"));
  1851. // Multi-f32 default installs all indices at once
  1852. let mut temp = Property::new(
  1853. "foo",
  1854. PropertyType::Float32,
  1855. PropertySubType::Color,
  1856. PropertyPermission::default(),
  1857. );
  1858. temp.set_array_len(4);
  1859. let prop = Arc::new(temp);
  1860. prop.set_default_f32_multi(&[0., 1., 2., 3.]).unwrap();
  1861. for i in 0..4 {
  1862. assert_eq!(prop.get_f32(i).unwrap(), i as f32);
  1863. }
  1864. }
  1865. // ------------------------------------------------------------------
  1866. // Expression defaults and effective source (task 2.2)
  1867. // ------------------------------------------------------------------
  1868. #[test]
  1869. fn test_default_expr_and_unset_override() {
  1870. let mut temp = Property::new(
  1871. "foo",
  1872. PropertyType::Float32,
  1873. PropertySubType::Null,
  1874. PropertyPermission::default(),
  1875. );
  1876. temp.allow_exprs();
  1877. let prop = Arc::new(temp);
  1878. let atom = &mut PropertyAtomicGuard::none();
  1879. // Default expression governs while the value slot is unset
  1880. prop.set_default_expr(0, vec![Op::ConstFloat32(10.)]).unwrap();
  1881. assert!(prop.is_expr(0).unwrap());
  1882. assert!(!prop.get_raw_value(0).unwrap().is_expr()); // source is the default
  1883. // Before first evaluation a concrete read succeeds with the type default
  1884. assert_eq!(prop.get_f32(0).unwrap(), 0.);
  1885. // Simulate an evaluation writing the cache
  1886. prop.set_cache_f32(atom, Role::Internal, 0, 10.).unwrap();
  1887. assert_eq!(prop.get_f32(0).unwrap(), 10.);
  1888. // Theme-style override: plain value wins, expr no longer effective
  1889. prop.set_f32(atom, Role::App, 0, 5.).unwrap();
  1890. assert!(!prop.is_expr(0).unwrap());
  1891. assert_eq!(prop.get_f32(0).unwrap(), 5.);
  1892. // Override expression (value slot) wins over the default expression
  1893. prop.set_expr(atom, Role::App, 0, vec![Op::ConstFloat32(20.)]).unwrap();
  1894. assert!(prop.is_expr(0).unwrap());
  1895. // One cache per index is shared between the two expression sources
  1896. // (design D3): until the next evaluation, reads observe the stale
  1897. // cache from the default expression — the window closes at the next
  1898. // draw pass, which the source switch triggers.
  1899. assert_eq!(prop.get_f32(0).unwrap(), 10.);
  1900. prop.set_cache_f32(atom, Role::Internal, 0, 20.).unwrap();
  1901. assert_eq!(prop.get_f32(0).unwrap(), 20.);
  1902. // Unsetting the override returns control to the default expression
  1903. prop.unset(atom, Role::App, 0).unwrap();
  1904. assert!(prop.is_expr(0).unwrap());
  1905. // Still the override's cached result until the next pass...
  1906. assert_eq!(prop.get_f32(0).unwrap(), 20.);
  1907. // ...which recomputes the default expression from scratch
  1908. prop.set_cache_f32(atom, Role::Internal, 0, 10.).unwrap();
  1909. assert_eq!(prop.get_f32(0).unwrap(), 10.);
  1910. }
  1911. #[test]
  1912. fn test_get_value_never_returns_expr() {
  1913. let mut temp = Property::new(
  1914. "foo",
  1915. PropertyType::Float32,
  1916. PropertySubType::Null,
  1917. PropertyPermission::default(),
  1918. );
  1919. temp.allow_exprs();
  1920. let prop = Arc::new(temp);
  1921. let atom = &mut PropertyAtomicGuard::none();
  1922. // Value-slot expr, never evaluated
  1923. prop.set_expr(atom, Role::App, 0, vec![Op::ConstFloat32(1.)]).unwrap();
  1924. assert!(matches!(prop.get_value(0).unwrap(), PropertyValue::Float32(_)));
  1925. // Default expr, never evaluated
  1926. prop.unset(atom, Role::App, 0).unwrap();
  1927. prop.set_default_expr(0, vec![Op::ConstFloat32(2.)]).unwrap();
  1928. assert!(matches!(prop.get_value(0).unwrap(), PropertyValue::Float32(_)));
  1929. assert_eq!(prop.get_f32(0).unwrap(), 0.);
  1930. // Builder variant round-trips through the same checks
  1931. let mut temp = Property::new(
  1932. "foo",
  1933. PropertyType::Float32,
  1934. PropertySubType::Null,
  1935. PropertyPermission::default(),
  1936. );
  1937. temp.allow_exprs();
  1938. assert!(temp.set_defaults_expr(vec![vec![Op::ConstFloat32(3.)]]).is_ok());
  1939. // Without allow_exprs it fails
  1940. let mut temp2 = Property::new(
  1941. "foo",
  1942. PropertyType::Float32,
  1943. PropertySubType::Null,
  1944. PropertyPermission::default(),
  1945. );
  1946. assert!(matches!(
  1947. temp2.set_defaults_expr(vec![vec![Op::ConstFloat32(3.)]]),
  1948. Err(Error::PropertySExprNotAllowed)
  1949. ));
  1950. }
  1951. // ------------------------------------------------------------------
  1952. // Role permissions (task 2.3)
  1953. // ------------------------------------------------------------------
  1954. #[test]
  1955. fn test_permission_denied_write_leaves_value() {
  1956. let mut temp = Property::new(
  1957. "foo",
  1958. PropertyType::Float32,
  1959. PropertySubType::Null,
  1960. PropertyPermission { read: Role::ALL, write: Role::Internal },
  1961. );
  1962. temp.set_defaults_f32(vec![1.]).unwrap();
  1963. let prop = Arc::new(temp);
  1964. let atom = &mut PropertyAtomicGuard::none();
  1965. // Allowed writer
  1966. prop.set_f32(atom, Role::Internal, 0, 5.).unwrap();
  1967. assert_eq!(prop.get_f32(0).unwrap(), 5.);
  1968. // Denied writer: error, value unchanged
  1969. assert!(matches!(
  1970. prop.set_f32(atom, Role::Theme, 0, 9.),
  1971. Err(Error::PropertyPermissionDenied)
  1972. ));
  1973. assert_eq!(prop.get_f32(0).unwrap(), 5.);
  1974. // Denied unset
  1975. assert!(matches!(prop.unset(atom, Role::User, 0), Err(Error::PropertyPermissionDenied)));
  1976. assert_eq!(prop.get_f32(0).unwrap(), 5.);
  1977. // Denied push (unbounded)
  1978. let mut temp = Property::new(
  1979. "foo",
  1980. PropertyType::Str,
  1981. PropertySubType::Null,
  1982. PropertyPermission { read: Role::ALL, write: Role::User },
  1983. );
  1984. temp.set_unbounded();
  1985. let prop = Arc::new(temp);
  1986. assert!(matches!(
  1987. prop.push_str(atom, Role::App, "x"),
  1988. Err(Error::PropertyPermissionDenied)
  1989. ));
  1990. assert_eq!(prop.get_len(), 0);
  1991. }
  1992. #[test]
  1993. fn test_permission_denied_wrapped_read() {
  1994. use crate::scene::{SceneNode, SceneNodeType};
  1995. let mut node = SceneNode::new("test", SceneNodeType::Null);
  1996. let mut temp = Property::new(
  1997. "secret",
  1998. PropertyType::Float32,
  1999. PropertySubType::Null,
  2000. // Readable by App only
  2001. PropertyPermission { read: Role::App, write: Role::ALL },
  2002. );
  2003. temp.set_defaults_f32(vec![3.]).unwrap();
  2004. node.add_property(temp).unwrap();
  2005. let node = Arc::new(node);
  2006. // Wrapping with a role lacking the read bit fails with
  2007. // PropertyPermissionDenied (validated upfront at wrap time since
  2008. // permissions are immutable).
  2009. assert!(matches!(
  2010. PropertyFloat32::wrap(&node, Role::Theme, "secret", 0),
  2011. Err(Error::PropertyPermissionDenied)
  2012. ));
  2013. // The allowed role wraps fine and reads the value
  2014. let wrapped = PropertyFloat32::wrap(&node, Role::App, "secret", 0).unwrap();
  2015. assert_eq!(wrapped.get(), 3.);
  2016. }
  2017. #[test]
  2018. fn test_permission_theme_denied_on_widget_owned() {
  2019. // D4/D13: widget-written runtime properties carry write masks
  2020. // without Theme, so a theme attempt fails instead of losing a
  2021. // write race.
  2022. let mut temp = Property::new(
  2023. "alpha",
  2024. PropertyType::Float32,
  2025. PropertySubType::Null,
  2026. PropertyPermission { read: Role::ALL, write: Role::Internal | Role::App },
  2027. );
  2028. temp.set_defaults_f32(vec![0.]).unwrap();
  2029. let prop = Arc::new(temp);
  2030. let atom = &mut PropertyAtomicGuard::none();
  2031. assert!(prop.can_write(Role::Internal));
  2032. assert!(prop.can_write(Role::App));
  2033. assert!(!prop.can_write(Role::Theme));
  2034. assert!(matches!(
  2035. prop.set_f32(atom, Role::Theme, 0, 1.),
  2036. Err(Error::PropertyPermissionDenied)
  2037. ));
  2038. // The widget's computed value stands
  2039. prop.set_f32(atom, Role::Internal, 0, 0.5).unwrap();
  2040. assert_eq!(prop.get_f32(0).unwrap(), 0.5);
  2041. }
  2042. #[test]
  2043. fn test_role_bitflags() {
  2044. let mask = Role::App | Role::Theme;
  2045. assert!(mask.contains(Role::App));
  2046. assert!(mask.contains(Role::Theme));
  2047. assert!(!mask.contains(Role::User));
  2048. assert!(!mask.contains(Role::Internal));
  2049. assert!(Role::ALL.contains(Role::User));
  2050. assert!(Role::ALL.contains(Role::Theme));
  2051. assert!(!Role::NONE.contains(Role::User));
  2052. assert!(mask.intersects(Role::User | Role::App));
  2053. assert!(!mask.intersects(Role::User | Role::Internal));
  2054. // Equality comparisons used by when_change filters still work
  2055. assert_eq!(Role::Internal, Role::Internal);
  2056. assert_ne!(Role::Internal, Role::Ignored);
  2057. }
  2058. // ------------------------------------------------------------------
  2059. // f32-array expression evaluation (task 3.1)
  2060. // ------------------------------------------------------------------
  2061. #[test]
  2062. fn test_eval_f32_multi_color_follows_token() {
  2063. use crate::{
  2064. expr,
  2065. scene::{SceneNode, SceneNodeType},
  2066. };
  2067. // Token property: a 4-component color with plain values
  2068. let mut token_temp = Property::new(
  2069. "accent",
  2070. PropertyType::Float32,
  2071. PropertySubType::Color,
  2072. PropertyPermission::default(),
  2073. );
  2074. token_temp.set_array_len(4);
  2075. let token = Arc::new(token_temp);
  2076. let atom = &mut PropertyAtomicGuard::none();
  2077. for i in 0..4 {
  2078. token.set_f32(atom, Role::App, i, i as f32 * 0.25).unwrap();
  2079. }
  2080. // Widget color property: per-index exprs referencing the token
  2081. let mut node = SceneNode::new("widget", SceneNodeType::Null);
  2082. let mut color_temp = Property::new(
  2083. "text_color",
  2084. PropertyType::Float32,
  2085. PropertySubType::Color,
  2086. PropertyPermission::default(),
  2087. );
  2088. color_temp.set_array_len(4);
  2089. color_temp.allow_exprs();
  2090. node.add_property(color_temp).unwrap();
  2091. let node = Arc::new(node);
  2092. let color = PropertyColor::wrap(&node, Role::Internal, "text_color").unwrap();
  2093. let prop = color.prop();
  2094. for i in 0..4 {
  2095. let local = format!("accent_{i}");
  2096. prop.set_default_expr(i, expr::load_var(&local)).unwrap();
  2097. prop.add_depend(Role::App, &token, i, local);
  2098. }
  2099. // Before evaluation, reads fall through to the type default
  2100. assert_eq!(prop.get_f32(0).unwrap(), 0.);
  2101. // Evaluate: results land in the cache and are returned by get_f32
  2102. color.eval(atom).unwrap();
  2103. for i in 0..4 {
  2104. assert_eq!(prop.get_f32(i).unwrap(), i as f32 * 0.25);
  2105. }
  2106. assert_eq!(color.get(), [0., 0.25, 0.5, 0.75]);
  2107. // Changing the token and re-evaluating recomputes every index
  2108. token.set_f32(atom, Role::App, 0, 1.).unwrap();
  2109. color.eval(atom).unwrap();
  2110. assert_eq!(color.get(), [1., 0.25, 0.5, 0.75]);
  2111. }
  2112. #[test]
  2113. fn test_eval_f32_multi_mixed_indices() {
  2114. use crate::{
  2115. expr,
  2116. scene::{SceneNode, SceneNodeType},
  2117. };
  2118. let token = {
  2119. let mut t = Property::new(
  2120. "size",
  2121. PropertyType::Float32,
  2122. PropertySubType::Pixel,
  2123. PropertyPermission::default(),
  2124. );
  2125. t.set_defaults_f32(vec![18.]).unwrap();
  2126. Arc::new(t)
  2127. };
  2128. // One expr index (0 → token) and one plain value (1 → 99.)
  2129. let mut node = SceneNode::new("widget", SceneNodeType::Null);
  2130. let mut temp = Property::new(
  2131. "geom",
  2132. PropertyType::Float32,
  2133. PropertySubType::Pixel,
  2134. PropertyPermission::default(),
  2135. );
  2136. temp.set_array_len(2);
  2137. temp.allow_exprs();
  2138. node.add_property(temp).unwrap();
  2139. let node = Arc::new(node);
  2140. let prop = node.get_property("geom").unwrap();
  2141. prop.set_default_expr(0, expr::load_var("size")).unwrap();
  2142. prop.add_depend(Role::App, &token, 0, "size");
  2143. let atom = &mut PropertyAtomicGuard::none();
  2144. prop.set_f32(atom, Role::App, 1, 99.).unwrap();
  2145. eval_f32_multi(&prop, atom, Role::Internal, &[0, 1], vec![]).unwrap();
  2146. // Only the expr index was recomputed; the plain index kept its value
  2147. assert_eq!(prop.get_f32(0).unwrap(), 18.);
  2148. assert_eq!(prop.get_f32(1).unwrap(), 99.);
  2149. assert!(prop.get_raw_value(1).unwrap().is_expr() == false);
  2150. // Single-f32 wrap variant evaluates its index from dependencies
  2151. let font_size = PropertyFloat32::wrap(&node, Role::Internal, "geom", 0).unwrap();
  2152. font_size.eval(atom).unwrap();
  2153. assert_eq!(font_size.get(), 18.);
  2154. }
  2155. }