attributes.rs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. use crate::core::{Attribute, AttributesData, AttributesRule, Operation};
  2. use std::{collections::HashMap, fmt, fmt::Formatter};
  3. #[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
  4. #[serde(untagged)]
  5. pub enum Attributes {
  6. #[serde(skip)]
  7. Follow,
  8. Custom(AttributesData),
  9. }
  10. impl fmt::Display for Attributes {
  11. fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
  12. match self {
  13. Attributes::Follow => f.write_str("follow"),
  14. Attributes::Custom(data) => f.write_fmt(format_args!("{}", data)),
  15. }
  16. }
  17. }
  18. impl Attributes {
  19. pub fn data(&self) -> Option<AttributesData> {
  20. match self {
  21. Attributes::Follow => None,
  22. Attributes::Custom(data) => Some(data.clone()),
  23. }
  24. }
  25. pub fn is_empty(&self) -> bool {
  26. match self {
  27. Attributes::Follow => false,
  28. Attributes::Custom(data) => data.is_empty(),
  29. }
  30. }
  31. }
  32. impl std::default::Default for Attributes {
  33. fn default() -> Self { Attributes::Custom(AttributesData::new()) }
  34. }
  35. pub(crate) fn attributes_from(operation: &Option<Operation>) -> Option<Attributes> {
  36. match operation {
  37. None => None,
  38. Some(operation) => Some(operation.get_attributes()),
  39. }
  40. }
  41. pub fn compose_operation(left: &Option<Operation>, right: &Option<Operation>) -> Attributes {
  42. if left.is_none() && right.is_none() {
  43. return Attributes::default();
  44. }
  45. let attr_l = attributes_from(left);
  46. let attr_r = attributes_from(right);
  47. if attr_l.is_none() {
  48. return attr_r.unwrap();
  49. }
  50. if attr_r.is_none() {
  51. return attr_l.unwrap();
  52. }
  53. compose_attributes(attr_l.unwrap(), attr_r.unwrap())
  54. }
  55. pub fn transform_operation(left: &Option<Operation>, right: &Option<Operation>) -> Attributes {
  56. let attr_l = attributes_from(left);
  57. let attr_r = attributes_from(right);
  58. if attr_l.is_none() {
  59. if attr_r.is_none() {
  60. return Attributes::default();
  61. }
  62. return match attr_r.as_ref().unwrap() {
  63. Attributes::Follow => Attributes::Follow,
  64. Attributes::Custom(_) => attr_r.unwrap(),
  65. };
  66. }
  67. transform_attributes(attr_l.unwrap(), attr_r.unwrap())
  68. }
  69. pub fn invert_attributes(attr: Attributes, base: Attributes) -> Attributes {
  70. let attr = attr.data();
  71. let base = base.data();
  72. if attr.is_none() && base.is_none() {
  73. return Attributes::default();
  74. }
  75. let attr = attr.unwrap_or(AttributesData::new());
  76. let base = base.unwrap_or(AttributesData::new());
  77. let base_inverted = base
  78. .iter()
  79. .fold(AttributesData::new(), |mut attributes, (k, v)| {
  80. if base.get(k) != attr.get(k) && attr.contains_key(k) {
  81. attributes.insert(k.clone(), v.clone());
  82. }
  83. attributes
  84. });
  85. let inverted = attr.iter().fold(base_inverted, |mut attributes, (k, _)| {
  86. if base.get(k) != attr.get(k) && !base.contains_key(k) {
  87. attributes.remove(k);
  88. }
  89. attributes
  90. });
  91. return Attributes::Custom(inverted);
  92. }
  93. pub fn merge_attributes(attributes: Attributes, other: Attributes) -> Attributes {
  94. match (&attributes, &other) {
  95. (Attributes::Custom(data), Attributes::Custom(o_data)) => {
  96. let mut data = data.clone();
  97. data.extend(Some(o_data.clone()), false);
  98. Attributes::Custom(data)
  99. },
  100. (Attributes::Custom(data), _) => Attributes::Custom(data.clone()),
  101. _ => other,
  102. }
  103. }
  104. fn compose_attributes(left: Attributes, right: Attributes) -> Attributes {
  105. log::trace!("compose_attributes: a: {:?}, b: {:?}", left, right);
  106. let attr = match (&left, &right) {
  107. (_, Attributes::Custom(_)) => merge_attributes(left, right),
  108. (Attributes::Custom(_), _) => merge_attributes(left, right),
  109. _ => Attributes::Follow,
  110. };
  111. log::trace!("composed_attributes: a: {:?}", attr);
  112. attr
  113. }
  114. fn transform_attributes(left: Attributes, right: Attributes) -> Attributes {
  115. match (left, right) {
  116. (Attributes::Custom(data_l), Attributes::Custom(data_r)) => {
  117. let result = data_r
  118. .iter()
  119. .fold(AttributesData::new(), |mut new_attr_data, (k, v)| {
  120. if !data_l.contains_key(k) {
  121. new_attr_data.insert(k.clone(), v.clone());
  122. }
  123. new_attr_data
  124. });
  125. Attributes::Custom(result)
  126. },
  127. _ => Attributes::default(),
  128. }
  129. }