1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
mod chained_jointbuilder;
mod chained_linkbuilder;
use std::{
fmt::Debug,
ops::{Deref, DerefMut},
};
use crate::identifiers::GroupIDChanger;
#[derive(Debug, PartialEq, Clone)]
pub struct Chained<Builder: ChainableBuilder>(pub(crate) Builder);
// impl<Builder> Chained<Builder>
// where
// Builder: ChainableBuilder,
// {
// /// TODONE: Maybe deprecate
// pub fn builder(&self) -> &Builder {
// &self.0
// }
// /// FIXEDME: This is not very usefull since most JointBuilder Methods are consuming
// /// TODONE: Maybe deprecate
// pub fn builder_mut(&mut self) -> &mut Builder {
// &mut self.0
// }
// /// TODONE: Maybe deprecate since Deref and DerefMut
// /// Allows the internal `Builder` and it's chain to be changed by a closure.
// ///
// /// If in this process the `Builder` has lost it's chain, for example due to overwriting.
// /// An error of type `Builder` is retured so the updated `Builder` can still be used.
// pub fn modify_builder<F>(self, mut f: F) -> Result<Self, Builder>
// where
// F: FnMut(Builder) -> Builder,
// {
// let builder = f(self.0);
// // When we are tricked into loosing our chain
// match builder.has_chain() {
// // The modified `Builder` still has a chain, therefor we can continue to assume our `Builder` has a chain and make a new `Chained<Builder>`.
// true => Ok(Self(builder)),
// // The modified `Builder` has does not have a chain, therefor we can not build chains with it.
// false => Err(builder),
// }
// }
// }
// To allow for calling functions on the internal builders
// TODO: Figure out if builderfunctions do not free the internal builder from it `Chained<Builder>` Identifier
//
// UPDATE: We do not escape however, the functions that consume can not be called either, see test chained::chained_joint_builder::test::chained escaping
// TODO: Solution?: Add inplace methods???
//
// FIXME: but deref should theoretically only be implemented for smartpointers which do not add methods
// https://rust-lang.github.io/api-guidelines/predictability.html?highlight=deref#only-smart-pointers-implement-deref-and-derefmut-c-deref
// https://rust-lang.github.io/api-guidelines/predictability.html?highlight=deref#smart-pointers-do-not-add-inherent-methods-c-smart-ptr
impl<Builder> Deref for Chained<Builder>
where
Builder: ChainableBuilder,
{
type Target = Builder;
fn deref(&self) -> &Self::Target {
&self.0
}
}
// To allow for calling functions on the internal builders
// TODO: See above
impl<Builder> DerefMut for Chained<Builder>
where
Builder: ChainableBuilder,
{
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[cfg(feature = "wrapper")]
impl<Builder> Chained<Builder>
where
Builder: ChainableBuilder,
{
/// Create a Chained Builder, needs to be a chain.
pub unsafe fn new(builder: Builder) -> Self {
Chained(builder)
}
}
pub trait ChainableBuilder: Debug + PartialEq + Clone + GroupIDChanger {
/// Returns `true` if the builder has a chain/one or more childeren.
fn has_chain(&self) -> bool;
}
#[cfg(test)]
mod tests {
use super::Chained;
use crate::{
joint::{JointBuilder, SmartJointBuilder},
link::{builder::LinkBuilder, Link},
prelude::*,
};
use test_log::test;
/// For my own conncept of `DerefMut`
#[test]
fn deref_mut_test() {
let leg_tree = Link::builder("leg_[[L01]]_l1").build_tree();
leg_tree
.get_root_link()
.try_write()
.unwrap()
.try_attach_child(
Link::builder("leg_[[L01]]_l2"),
SmartJointBuilder::new_fixed("leg_[[L01]]_j1"),
)
.unwrap();
let tree = Link::builder("root").build_tree();
tree.get_root_link()
.try_write()
.unwrap()
.try_attach_child(leg_tree, SmartJointBuilder::new_fixed("leg_[[L01]]_j0"))
.unwrap();
let builder_chain = tree.yank_joint("leg_[[L01]]_j0").unwrap();
assert_eq!(
builder_chain,
Chained(JointBuilder {
name: "leg_[[L01]]_j0".into(),
child: Some(LinkBuilder {
name: "leg_[[L01]]_l1".into(),
joints: vec![JointBuilder {
name: "leg_[[L01]]_j1".into(),
child: Some(LinkBuilder {
name: "leg_[[L01]]_l2".into(),
..Default::default()
}),
..Default::default()
}],
..Default::default()
}),
..Default::default()
})
);
let mut mirrored_chain = builder_chain
.clone()
.mirror(crate::transform::MirrorAxis::X);
// TODO: Add chainable version?
mirrored_chain.change_group_id("R01").unwrap();
let tree = Link::builder("root").build_tree();
tree.get_root_link()
.try_write()
.unwrap()
.attach_joint_chain(builder_chain)
.unwrap();
tree.get_root_link()
.try_write()
.unwrap()
.attach_joint_chain(mirrored_chain)
.unwrap();
assert_eq!(
tree.yank_link("root").unwrap(),
Chained(LinkBuilder {
name: "root".into(),
joints: vec![
JointBuilder {
name: "leg_[[L01]]_j0".into(),
child: Some(LinkBuilder {
name: "leg_[[L01]]_l1".into(),
joints: vec![JointBuilder {
name: "leg_[[L01]]_j1".into(),
child: Some(LinkBuilder {
name: "leg_[[L01]]_l2".into(),
..Default::default()
}),
..Default::default()
}],
..Default::default()
}),
..Default::default()
},
JointBuilder {
name: "leg_[[R01]]_j0".into(),
child: Some(LinkBuilder {
name: "leg_[[R01]]_l1".into(),
joints: vec![JointBuilder {
name: "leg_[[R01]]_j1".into(),
child: Some(LinkBuilder {
name: "leg_[[R01]]_l2".into(),
..Default::default()
}),
..Default::default()
}],
..Default::default()
}),
..Default::default()
}
],
..Default::default()
})
)
}
}