prop.rs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645
  1. use crate::error::{Error, Result};
  2. use atomic_float::AtomicF32;
  3. use darkfi_serial::{Encodable, SerialDecodable, SerialEncodable, WriteExt};
  4. use std::{
  5. fmt,
  6. io::Write,
  7. str::FromStr,
  8. sync::{
  9. atomic::{AtomicBool, AtomicU32, Ordering},
  10. Arc, Mutex, MutexGuard,
  11. },
  12. };
  13. use crate::{expr::SExprCode, scene::SceneNodeId};
  14. type Buffer = Arc<Vec<u8>>;
  15. #[derive(Debug, Copy, Clone, PartialEq, SerialEncodable, SerialDecodable)]
  16. #[repr(u8)]
  17. pub enum PropertyType {
  18. Null = 0,
  19. Bool = 1,
  20. Uint32 = 2,
  21. Float32 = 3,
  22. Str = 4,
  23. Enum = 5,
  24. Buffer = 6,
  25. SceneNodeId = 7,
  26. SExpr = 8,
  27. }
  28. impl PropertyType {
  29. fn default_value(&self) -> PropertyValue {
  30. match self {
  31. Self::Null => PropertyValue::Null,
  32. Self::Bool => PropertyValue::Bool(false),
  33. Self::Uint32 => PropertyValue::Uint32(0),
  34. Self::Float32 => PropertyValue::Float32(0.),
  35. Self::Str => PropertyValue::Str(String::new()),
  36. Self::Enum => PropertyValue::Enum(String::new()),
  37. Self::Buffer => PropertyValue::Buffer(Arc::new(vec![])),
  38. Self::SceneNodeId => PropertyValue::SceneNodeId(0),
  39. Self::SExpr => PropertyValue::SExpr(Arc::new(vec![])),
  40. }
  41. }
  42. }
  43. #[derive(Debug, Copy, Clone, PartialEq, SerialEncodable, SerialDecodable)]
  44. #[repr(u8)]
  45. pub enum PropertySubType {
  46. Null = 0,
  47. Color = 1,
  48. // Size of something in pixels
  49. Pixel = 2,
  50. ResourceId = 3,
  51. }
  52. #[derive(Debug, Clone)]
  53. pub enum PropertyValue {
  54. Unset,
  55. Null,
  56. Bool(bool),
  57. Uint32(u32),
  58. Float32(f32),
  59. Str(String),
  60. Enum(String),
  61. Buffer(Arc<Vec<u8>>),
  62. SceneNodeId(SceneNodeId),
  63. SExpr(Arc<SExprCode>),
  64. }
  65. impl PropertyValue {
  66. fn as_type(&self) -> PropertyType {
  67. match self {
  68. Self::Unset => todo!("not sure"),
  69. Self::Null => PropertyType::Null,
  70. Self::Bool(_) => PropertyType::Bool,
  71. Self::Uint32(_) => PropertyType::Uint32,
  72. Self::Float32(_) => PropertyType::Float32,
  73. Self::Str(_) => PropertyType::Str,
  74. Self::Enum(_) => PropertyType::Enum,
  75. Self::Buffer(_) => PropertyType::Buffer,
  76. Self::SceneNodeId(_) => PropertyType::SceneNodeId,
  77. Self::SExpr(_) => PropertyType::SExpr,
  78. }
  79. }
  80. pub fn is_unset(&self) -> bool {
  81. match self {
  82. Self::Unset => true,
  83. _ => false,
  84. }
  85. }
  86. pub fn is_null(&self) -> bool {
  87. match self {
  88. Self::Null => true,
  89. _ => false,
  90. }
  91. }
  92. pub fn is_expr(&self) -> bool {
  93. match self {
  94. Self::SExpr(_) => true,
  95. _ => false,
  96. }
  97. }
  98. fn as_bool(&self) -> Result<bool> {
  99. match self {
  100. Self::Bool(v) => Ok(*v),
  101. _ => Err(Error::PropertyWrongType),
  102. }
  103. }
  104. fn as_u32(&self) -> Result<u32> {
  105. match self {
  106. Self::Uint32(v) => Ok(*v),
  107. _ => Err(Error::PropertyWrongType),
  108. }
  109. }
  110. fn as_f32(&self) -> Result<f32> {
  111. match self {
  112. Self::Float32(v) => Ok(*v),
  113. _ => Err(Error::PropertyWrongType),
  114. }
  115. }
  116. fn as_str(&self) -> Result<String> {
  117. match self {
  118. Self::Str(v) => Ok(v.clone()),
  119. _ => Err(Error::PropertyWrongType),
  120. }
  121. }
  122. fn as_enum(&self) -> Result<String> {
  123. match self {
  124. Self::Enum(v) => Ok(v.clone()),
  125. _ => Err(Error::PropertyWrongType),
  126. }
  127. }
  128. fn as_buf(&self) -> Result<Buffer> {
  129. match self {
  130. Self::Buffer(v) => Ok(v.clone()),
  131. _ => Err(Error::PropertyWrongType),
  132. }
  133. }
  134. fn as_node_id(&self) -> Result<SceneNodeId> {
  135. match self {
  136. Self::SceneNodeId(v) => Ok(*v),
  137. _ => Err(Error::PropertyWrongType),
  138. }
  139. }
  140. fn as_sexpr(&self) -> Result<Arc<SExprCode>> {
  141. match self {
  142. Self::SExpr(v) => Ok(v.clone()),
  143. _ => Err(Error::PropertyWrongType),
  144. }
  145. }
  146. }
  147. impl Encodable for PropertyValue {
  148. fn encode<S: Write>(&self, s: &mut S) -> std::result::Result<usize, std::io::Error> {
  149. match self {
  150. Self::Unset | Self::Null | Self::Buffer(_) => {
  151. // do nothing
  152. Ok(0)
  153. }
  154. Self::Bool(v) => v.encode(s),
  155. Self::Uint32(v) => v.encode(s),
  156. Self::Float32(v) => v.encode(s),
  157. Self::Str(v) => v.encode(s),
  158. Self::Enum(v) => v.encode(s),
  159. Self::SceneNodeId(v) => v.encode(s),
  160. Self::SExpr(v) => v.encode(s),
  161. }
  162. }
  163. }
  164. pub struct Property {
  165. pub name: String,
  166. pub typ: PropertyType,
  167. pub subtype: PropertySubType,
  168. pub defaults: Vec<PropertyValue>,
  169. pub vals: Mutex<Vec<PropertyValue>>,
  170. pub ui_name: String,
  171. pub desc: String,
  172. pub is_null_allowed: bool,
  173. pub is_expr_allowed: bool,
  174. // Use 0 for unbounded length
  175. pub array_len: usize,
  176. pub min_val: Option<PropertyValue>,
  177. pub max_val: Option<PropertyValue>,
  178. // PropertyType must be Enum
  179. pub enum_items: Option<Vec<String>>,
  180. }
  181. impl Property {
  182. pub fn new<S: Into<String>>(name: S, typ: PropertyType, subtype: PropertySubType) -> Self {
  183. Self {
  184. name: name.into(),
  185. typ,
  186. subtype,
  187. defaults: vec![typ.default_value()],
  188. vals: Mutex::new(vec![PropertyValue::Unset]),
  189. ui_name: String::new(),
  190. desc: String::new(),
  191. is_null_allowed: false,
  192. is_expr_allowed: false,
  193. array_len: 1,
  194. min_val: None,
  195. max_val: None,
  196. enum_items: None,
  197. }
  198. }
  199. pub fn set_ui_text<S: Into<String>>(&mut self, ui_name: S, desc: S) {
  200. self.ui_name = ui_name.into();
  201. self.desc = desc.into();
  202. }
  203. pub fn set_array_len(&mut self, len: usize) {
  204. self.array_len = len;
  205. self.defaults.resize(len, self.typ.default_value());
  206. self.vals.lock().unwrap().resize(len, PropertyValue::Unset);
  207. }
  208. pub fn set_unbounded(&mut self) {
  209. self.set_array_len(0);
  210. }
  211. pub fn set_range_u32(&mut self, min: u32, max: u32) {
  212. self.min_val = Some(PropertyValue::Uint32(min));
  213. self.max_val = Some(PropertyValue::Uint32(max));
  214. }
  215. pub fn set_range_f32(&mut self, min: f32, max: f32) {
  216. self.min_val = Some(PropertyValue::Float32(min));
  217. self.max_val = Some(PropertyValue::Float32(max));
  218. }
  219. pub fn set_enum_items<S: Into<String>>(&mut self, enum_items: Vec<S>) -> Result<()> {
  220. if self.typ != PropertyType::Enum {
  221. return Err(Error::PropertyWrongType)
  222. }
  223. self.enum_items = Some(enum_items.into_iter().map(|item| item.into()).collect());
  224. Ok(())
  225. }
  226. pub fn allow_null_values(&mut self) {
  227. self.is_null_allowed = true;
  228. }
  229. pub fn allow_exprs(&mut self) {
  230. self.is_expr_allowed = true;
  231. }
  232. fn check_defaults_len(&self, defaults_len: usize) -> Result<()> {
  233. if !self.is_bounded() || defaults_len != self.array_len {
  234. return Err(Error::PropertyWrongLen)
  235. }
  236. Ok(())
  237. }
  238. pub fn set_defaults_u32(&mut self, defaults: Vec<u32>) -> Result<()> {
  239. self.check_defaults_len(defaults.len())?;
  240. self.defaults = defaults.into_iter().map(|v| PropertyValue::Uint32(v)).collect();
  241. Ok(())
  242. }
  243. pub fn set_defaults_f32(&mut self, defaults: Vec<f32>) -> Result<()> {
  244. self.check_defaults_len(defaults.len())?;
  245. self.defaults = defaults.into_iter().map(|v| PropertyValue::Float32(v)).collect();
  246. Ok(())
  247. }
  248. pub fn set_defaults_str(&mut self, defaults: Vec<String>) -> Result<()> {
  249. self.check_defaults_len(defaults.len())?;
  250. self.defaults = defaults.into_iter().map(|v| PropertyValue::Str(v)).collect();
  251. Ok(())
  252. }
  253. /// This will clear all values, resetting them to the default
  254. pub fn clear_values(&self) {
  255. let vals = &mut self.vals.lock().unwrap();
  256. vals.clear();
  257. vals.resize(self.array_len, PropertyValue::Unset);
  258. }
  259. // Set
  260. fn set_raw_value(&self, i: usize, val: PropertyValue) -> Result<()> {
  261. if self.typ != val.as_type() {
  262. return Err(Error::PropertyWrongType)
  263. }
  264. let vals = &mut self.vals.lock().unwrap();
  265. if i >= vals.len() {
  266. return Err(Error::PropertyWrongIndex)
  267. }
  268. vals[i] = val;
  269. Ok(())
  270. }
  271. pub fn unset(&self, i: usize) -> Result<()> {
  272. let vals = &mut self.vals.lock().unwrap();
  273. if i >= vals.len() {
  274. return Err(Error::PropertyWrongIndex)
  275. }
  276. vals[i] = PropertyValue::Unset;
  277. Ok(())
  278. }
  279. pub fn set_null(&self, i: usize) -> Result<()> {
  280. if !self.is_null_allowed {
  281. return Err(Error::PropertyNullNotAllowed)
  282. }
  283. let vals = &mut self.vals.lock().unwrap();
  284. if i >= vals.len() {
  285. return Err(Error::PropertyWrongIndex)
  286. }
  287. vals[i] = PropertyValue::Null;
  288. Ok(())
  289. }
  290. pub fn set_bool(&self, i: usize, val: bool) -> Result<()> {
  291. self.set_raw_value(i, PropertyValue::Bool(val))
  292. }
  293. pub fn set_u32(&self, i: usize, val: u32) -> Result<()> {
  294. if self.min_val.is_some() {
  295. let min = self.min_val.as_ref().unwrap().as_u32()?;
  296. if val < min {
  297. return Err(Error::PropertyOutOfRange);
  298. }
  299. }
  300. if self.max_val.is_some() {
  301. let max = self.max_val.as_ref().unwrap().as_u32()?;
  302. if val > max {
  303. return Err(Error::PropertyOutOfRange);
  304. }
  305. }
  306. self.set_raw_value(i, PropertyValue::Uint32(val))
  307. }
  308. pub fn set_f32(&self, i: usize, val: f32) -> Result<()> {
  309. if self.min_val.is_some() {
  310. let min = self.min_val.as_ref().unwrap().as_f32()?;
  311. if val < min {
  312. return Err(Error::PropertyOutOfRange);
  313. }
  314. }
  315. if self.max_val.is_some() {
  316. let max = self.max_val.as_ref().unwrap().as_f32()?;
  317. if val > max {
  318. return Err(Error::PropertyOutOfRange);
  319. }
  320. }
  321. self.set_raw_value(i, PropertyValue::Float32(val))
  322. }
  323. pub fn set_str<S: Into<String>>(&self, i: usize, val: S) -> Result<()> {
  324. self.set_raw_value(i, PropertyValue::Str(val.into()))
  325. }
  326. pub fn set_enum<S: Into<String>>(&self, i: usize, val: S) -> Result<()> {
  327. if self.typ != PropertyType::Enum {
  328. return Err(Error::PropertyWrongType)
  329. }
  330. let val = val.into();
  331. if !self.enum_items.as_ref().unwrap().contains(&val) {
  332. return Err(Error::PropertyWrongEnumItem)
  333. }
  334. self.set_raw_value(i, PropertyValue::Enum(val.into()))
  335. }
  336. pub fn set_buf(&self, i: usize, val: Vec<u8>) -> Result<()> {
  337. self.set_raw_value(i, PropertyValue::Buffer(Arc::new(val)))
  338. }
  339. pub fn set_node_id(&self, i: usize, val: SceneNodeId) -> Result<()> {
  340. self.set_raw_value(i, PropertyValue::SceneNodeId(val))
  341. }
  342. pub fn set_expr(&self, i: usize, val: SExprCode) -> Result<()> {
  343. if !self.is_expr_allowed {
  344. return Err(Error::PropertySExprNotAllowed)
  345. }
  346. let vals = &mut self.vals.lock().unwrap();
  347. if i >= vals.len() {
  348. return Err(Error::PropertyWrongIndex)
  349. }
  350. vals[i] = PropertyValue::SExpr(Arc::new(val));
  351. Ok(())
  352. }
  353. // Push
  354. pub fn push_null(&self) -> Result<usize> {
  355. if self.is_bounded() {
  356. return Err(Error::PropertyIsBounded)
  357. }
  358. let vals = &mut self.vals.lock().unwrap();
  359. let i = vals.len();
  360. vals.push(PropertyValue::Null);
  361. Ok(i)
  362. }
  363. pub fn push_bool(&self, val: bool) -> Result<usize> {
  364. let i = self.push_null()?;
  365. self.set_bool(i, val)?;
  366. Ok(i)
  367. }
  368. pub fn push_u32(&self, val: u32) -> Result<usize> {
  369. let i = self.push_null()?;
  370. self.set_u32(i, val)?;
  371. Ok(i)
  372. }
  373. pub fn push_f32(&self, val: f32) -> Result<usize> {
  374. let i = self.push_null()?;
  375. self.set_f32(i, val)?;
  376. Ok(i)
  377. }
  378. pub fn push_str<S: Into<String>>(&self, val: S) -> Result<usize> {
  379. let i = self.push_null()?;
  380. self.set_str(i, val)?;
  381. Ok(i)
  382. }
  383. pub fn push_enum<S: Into<String>>(&self, val: S) -> Result<usize> {
  384. let i = self.push_null()?;
  385. self.set_enum(i, val)?;
  386. Ok(i)
  387. }
  388. pub fn push_buf(&self, val: Vec<u8>) -> Result<usize> {
  389. let i = self.push_null()?;
  390. self.set_buf(i, val)?;
  391. Ok(i)
  392. }
  393. pub fn push_node_id(&self, val: SceneNodeId) -> Result<usize> {
  394. let i = self.push_null()?;
  395. self.set_node_id(i, val)?;
  396. Ok(i)
  397. }
  398. // Get
  399. fn is_bounded(&self) -> bool {
  400. self.array_len != 0
  401. }
  402. pub fn get_len(&self) -> usize {
  403. // Avoid locking unless we need to
  404. // If array len is nonzero, then vals len should be the same.
  405. if !self.is_bounded() {
  406. return self.vals.lock().unwrap().len()
  407. }
  408. self.array_len
  409. }
  410. pub fn is_unset(&self, i: usize) -> Result<bool> {
  411. let val = self.get_raw_value(i)?;
  412. Ok(val.is_unset())
  413. }
  414. pub fn is_expr(&self, i: usize) -> Result<bool> {
  415. if !self.is_expr_allowed {
  416. return Ok(false)
  417. }
  418. let val = self.get_raw_value(i)?;
  419. Ok(val.is_expr())
  420. }
  421. pub fn get_raw_value(&self, i: usize) -> Result<PropertyValue> {
  422. let vals = &self.vals.lock().unwrap();
  423. if self.is_bounded() {
  424. assert_eq!(vals.len(), self.array_len);
  425. }
  426. if i >= vals.len() {
  427. return Err(Error::PropertyWrongIndex)
  428. }
  429. Ok(vals[i].clone())
  430. }
  431. pub fn get_value(&self, i: usize) -> Result<PropertyValue> {
  432. let val = self.get_raw_value(i)?;
  433. if val.is_unset() {
  434. return Ok(self.defaults[i].clone())
  435. }
  436. Ok(val)
  437. }
  438. pub fn get_bool(&self, i: usize) -> Result<bool> {
  439. self.get_value(i)?.as_bool()
  440. }
  441. pub fn get_bool_opt(&self, i: usize) -> Result<Option<bool>> {
  442. let val = self.get_value(i)?;
  443. if val.is_null() {
  444. return Ok(None)
  445. }
  446. Ok(Some(val.as_bool()?))
  447. }
  448. pub fn get_u32(&self, i: usize) -> Result<u32> {
  449. self.get_value(i)?.as_u32()
  450. }
  451. pub fn get_u32_opt(&self, i: usize) -> Result<Option<u32>> {
  452. let val = self.get_value(i)?;
  453. if val.is_null() {
  454. return Ok(None)
  455. }
  456. Ok(Some(val.as_u32()?))
  457. }
  458. pub fn get_f32(&self, i: usize) -> Result<f32> {
  459. self.get_value(i)?.as_f32()
  460. }
  461. pub fn get_f32_opt(&self, i: usize) -> Result<Option<f32>> {
  462. let val = self.get_value(i)?;
  463. if val.is_null() {
  464. return Ok(None)
  465. }
  466. Ok(Some(val.as_f32()?))
  467. }
  468. pub fn get_str(&self, i: usize) -> Result<String> {
  469. self.get_value(i)?.as_str()
  470. }
  471. pub fn get_str_opt(&self, i: usize) -> Result<Option<String>> {
  472. let val = self.get_value(i)?;
  473. if val.is_null() {
  474. return Ok(None)
  475. }
  476. Ok(Some(val.as_str()?))
  477. }
  478. pub fn get_enum(&self, i: usize) -> Result<String> {
  479. self.get_value(i)?.as_enum()
  480. }
  481. pub fn get_enum_opt(&self, i: usize) -> Result<Option<String>> {
  482. let val = self.get_value(i)?;
  483. if val.is_null() {
  484. return Ok(None)
  485. }
  486. Ok(Some(val.as_enum()?))
  487. }
  488. pub fn get_buf(&self, i: usize) -> Result<Buffer> {
  489. self.get_value(i)?.as_buf()
  490. }
  491. pub fn get_buf_opt(&self, i: usize) -> Result<Option<Buffer>> {
  492. let val = self.get_value(i)?;
  493. if val.is_null() {
  494. return Ok(None)
  495. }
  496. Ok(Some(val.as_buf()?))
  497. }
  498. pub fn get_node_id(&self, i: usize) -> Result<SceneNodeId> {
  499. self.get_value(i)?.as_node_id()
  500. }
  501. pub fn get_node_id_opt(&self, i: usize) -> Result<Option<SceneNodeId>> {
  502. let val = self.get_value(i)?;
  503. if val.is_null() {
  504. return Ok(None)
  505. }
  506. Ok(Some(val.as_node_id()?))
  507. }
  508. pub fn get_expr(&self, i: usize) -> Result<Arc<SExprCode>> {
  509. self.get_value(i)?.as_sexpr()
  510. }
  511. }
  512. #[cfg(test)]
  513. mod tests {
  514. use super::*;
  515. #[test]
  516. fn test_getset() {
  517. let mut prop = Property::new("foo", PropertyType::Float32, PropertySubType::Null);
  518. assert!(prop.set_f32(1, 4.).is_err());
  519. assert!(prop.is_unset(0).unwrap());
  520. assert!(prop.set_f32(0, 4.).is_ok());
  521. assert_eq!(prop.get_f32(0).unwrap(), 4.);
  522. assert!(!prop.is_unset(0).unwrap());
  523. prop.unset(0).unwrap();
  524. assert!(prop.is_unset(0).unwrap());
  525. assert_eq!(prop.get_f32(0).unwrap(), 0.);
  526. }
  527. #[test]
  528. fn test_nullable() {
  529. // default len is 1
  530. let mut prop = Property::new("foo", PropertyType::Float32, PropertySubType::Null);
  531. assert!(prop.set_defaults_f32(vec![1.0, 0.0]).is_err());
  532. assert!(prop.set_defaults_f32(vec![2.0]).is_ok());
  533. prop.allow_null_values();
  534. prop.set_null(0).unwrap();
  535. assert!(prop.get_f32_opt(1).is_err());
  536. assert!(prop.get_f32_opt(0).is_ok());
  537. assert!(prop.get_f32_opt(0).unwrap().is_none());
  538. prop.clear_values();
  539. assert!(prop.get_f32(0).is_ok());
  540. assert!(prop.get_f32_opt(0).unwrap().is_some());
  541. assert_eq!(prop.get_f32(0).unwrap(), 2.0);
  542. }
  543. #[test]
  544. fn test_nonnullable() {
  545. let mut prop = Property::new("foo", PropertyType::Float32, PropertySubType::Null);
  546. assert!(prop.set_null(0).is_err());
  547. assert!(prop.is_unset(0).unwrap());
  548. }
  549. #[test]
  550. fn test_unbounded() {
  551. let mut prop = Property::new("foo", PropertyType::Float32, PropertySubType::Null);
  552. prop.set_unbounded();
  553. assert_eq!(prop.get_len(), 0);
  554. prop.push_f32(2.0).unwrap();
  555. prop.push_f32(3.0).unwrap();
  556. assert_eq!(prop.get_len(), 2);
  557. prop.clear_values();
  558. assert_eq!(prop.get_len(), 0);
  559. prop.allow_null_values();
  560. prop.push_null().unwrap();
  561. prop.push_f32(4.0).unwrap();
  562. prop.push_f32(5.0).unwrap();
  563. assert_eq!(prop.get_len(), 3);
  564. assert!(prop.get_f32_opt(0).unwrap().is_none());
  565. assert!(prop.get_f32_opt(1).unwrap().is_some());
  566. assert!(prop.get_f32_opt(2).unwrap().is_some());
  567. assert!(prop.get_f32_opt(3).is_err());
  568. let mut prop2 = Property::new("foo", PropertyType::Float32, PropertySubType::Null);
  569. assert!(prop2.push_f32(4.0).is_err());
  570. }
  571. #[test]
  572. fn test_range() {
  573. let mut prop = Property::new("foo", PropertyType::Float32, PropertySubType::Null);
  574. let half_pi = 3.1415926535 / 2.;
  575. prop.set_range_f32(-half_pi, half_pi);
  576. assert!(prop.set_f32(0, 6.).is_err());
  577. assert!(prop.set_f32(0, 1.).is_ok());
  578. }
  579. #[test]
  580. fn test_enum() {
  581. let mut prop = Property::new("foo", PropertyType::Enum, PropertySubType::Null);
  582. prop.set_enum_items(vec!["ABC", "XYZ", "FOO"]).unwrap();
  583. assert!(prop.set_enum(0, "ABC").is_ok());
  584. assert!(prop.set_enum(0, "BAR").is_err());
  585. }
  586. }