# orx-pseudo-default [![orx-pseudo-default crate](https://img.shields.io/crates/v/orx-pseudo-default.svg)](https://crates.io/crates/orx-pseudo-default) [![orx-pseudo-default documentation](https://docs.rs/orx-pseudo-default/badge.svg)](https://docs.rs/orx-pseudo-default) `PseudoDefault` trait allows to create a cheap default instance of a type, which **does not claim to be useful**. The difference of `PseudoDefault` from `Default` is the relaxed expectation of the created instance to be useful. The main use case of the trait is when we need to create a cheap instance of a type without any arguments, only to throw away afterwards. Therefore, created instance does not need to be a decent one. This trait allows to avoid unsafe code in certain use cases. For instance: * We can avoid tricks such as uninit, manually-drop, etc. that requires to be extremely careful, when we could've actually created a valid instance much more easily. * We can use pseudo-default to fill the gaps when we need to take out an element from a collection of types that cannot implement Default. Note that pseudo-default requirement is more relaxed than that of default, and hence, * types implementing Default can implement PseudoDefault, * additionally, types that cannot implement Default can manually implement PseudoDefault, provided that it is safe and cheap to create a pseudo instance of the type without any arguments. # Example Consider the following fictional type `Share` which divides a whole into pieces. Without providing the `number_of_shares`, this type does not have a meaning. **Therefore, we cannot justify implementing `Default`, it would be misleading.** If we still need to be able to create Share's for some reason, we can simply use `pseudo_default`. We would know that the created type does not promise to make sense behaviorally; however, it is still a cheap and valid instance that can be safely dropped. ```rust use orx_pseudo_default::PseudoDefault; struct Share { number_of_shares: std::num::NonZeroUsize, } impl Share { fn share_size(&self, whole_amount: usize) -> usize { whole_amount / self.number_of_shares } } impl PseudoDefault for Share { fn pseudo_default() -> Self { Self { number_of_shares: std::num::NonZeroUsize::new(1).unwrap(), } } } ``` A more advanced use case could be the following. Assume that we are trying to create a vec wrapper called `TakeVec` with the following features; * it allows to take out elements by index by a method called `take` * we should be able to wrap an allocated vec without any additional allocation * we need to be able to give back the originally allocated vec * we want to achieve this without unsafe code It is trivial to implement this with `Default` but we want to be less restrictive on the constraint so that it works for non-default types as well. We can use PseudoDefault for this. ```rust use orx_pseudo_default::PseudoDefault; struct TakeVec(Vec); impl From> for TakeVec { fn from(inner: Vec) -> Self { Self(inner) } } impl From> for Vec { fn from(value: TakeVec) -> Self { value.0 } } impl TakeVec { fn take(&mut self, index: usize) -> Option { self.0.get_mut(index).map(|element| { let mut value = T::pseudo_default(); std::mem::swap(&mut value, element); value }) } } // implemented default types let mut vec: TakeVec<_> = vec![0, 1, 2, 3].into(); assert_eq!(vec.take(2), Some(2)); let mut vec: TakeVec<_> = vec![0.to_string(), 1.to_string()].into(); assert_eq!(vec.take(0), Some(String::from("0"))); // non-default types let mut vec: TakeVec<_> = vec![ Share { number_of_shares: std::num::NonZeroUsize::new(42).unwrap(), }, Share { number_of_shares: std::num::NonZeroUsize::new(7).unwrap(), }, ] .into(); assert_eq!(vec.take(0).map(|x| x.number_of_shares.into()), Some(42)); ``` ### Derive Similar to `Default`, it is possible to derive `PseudoDefault` provided that all members also implement `PseudoDefault`. ```rust use orx_pseudo_default::*; #[derive(PseudoDefault)] struct ChildStruct { a: String, b: char, c: Vec, } #[derive(PseudoDefault)] struct MyStruct { x: ChildStruct, y: bool, z: Option, } assert_eq!(String::pseudo_default(), MyStruct::pseudo_default().x.a); assert_eq!(char::pseudo_default(), MyStruct::pseudo_default().x.b); assert_eq!(Vec::::pseudo_default(), MyStruct::pseudo_default().x.c); assert_eq!(bool::pseudo_default(), MyStruct::pseudo_default().y); assert_eq!( Option::::pseudo_default(), MyStruct::pseudo_default().z ); ``` ## Contributing Contributions are welcome! If you notice an error, have a question or think something could be improved, please open an [issue](https://github.com/orxfun/orx-pseudo-default/issues/new) or create a PR. ## License This library is licensed under MIT license. See LICENSE for details.