mod.rs 19 KB

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